حد الانضمام إلى صف واحد
-
11-12-2019 - |
سؤال
لدي الاستعلام التالي:
SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as
"creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".*
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id")
JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId")
JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" )
JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId")
JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null
GROUP BY "Clients".id, "Rmas".id;
المشكلة هي أن الجدول "EsnsSalesOrderItems"
يمكن أن يكون لها نفس الشيء EsnId
في إدخالات مختلفة.أريد تقييد الاستعلام لسحب الإدخال الأخير فقط "EsnsSalesOrderItems"
هذا له نفس الشيء "EsnId"
.
عن طريق إدخال" آخر " أعني ما يلي:
الذي يظهر آخر في الجدول "EsnsSalesOrderItems"
.لذلك على سبيل المثال إذا "EsnsSalesOrderItems"
لديه اثنين من الإدخالات مع "EsnId" = 6
و "createdAt" = '2012-06-19'
و '2012-07-19'
على التوالي يجب أن تعطيني فقط الدخول من '2012-07-19'
.
المحلول
SELECT (count(*) * sum(s."price")) AS amount
, 'rma' AS "creditType"
, c."company" AS "client"
, c.id AS "ClientId"
, r.*
FROM "Rmas" r
JOIN "EsnsRmas" er ON er."RmaId" = r."id"
JOIN "Esns" e ON e.id = er."EsnId"
JOIN (
SELECT DISTINCT ON ("EsnId") *
FROM "EsnsSalesOrderItems"
ORDER BY "EsnId", "createdAt" DESC
) es ON es."EsnId" = e."id"
JOIN "SalesOrderItems" s ON s."id" = es."SalesOrderItemId"
JOIN "Clients" c ON c."id" = r."ClientId"
WHERE r."credited" = FALSE
AND r."verifyStatus" IS NOT NULL
GROUP BY c.id, r.id;
يحتوي استفسارك في السؤال على تجميع غير قانوني على إجمالي آخر:
sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
مبسطة وتحويلها إلى بناء الجملة القانوني:
(count(*) * sum(s."price")) AS amount
ولكن هل تريد حقا أن تتضاعف مع عدد لكل مجموعة?
أنا استرداد صف واحد لكل مجموعة في "EsnsSalesOrderItems"
مع DISTINCT ON
.شرح مفصل:
وأضفت أيضا الأسماء المستعارة الجدول والتنسيق لجعل الاستعلام أسهل لتحليل للعيون البشرية.إذا كنت تستطيع تجنب حالة الجمل هل يمكن التخلص من جميع علامات الاقتباس المزدوجة تغيم المنظر.
نصائح أخرى
شيء مثل:
join (
select "EsnId",
row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1
سيؤدي هذا إلى تحديد الأحدث "EsnId"
من "EsnsSalesOrderItems"
على أساس العمود creation_date
.نظرًا لأنك لم تنشر بنية جداولك، فقد اضطررت إلى "ابتكار" اسم عمود.يمكنك استخدام أي عمود يسمح لك بتحديد ترتيب على الصفوف التي تناسبك.
لكن تذكر أن مفهوم "الصف الأخير" يكون صالحًا فقط إذا قمت بتحديد طلب أو صفوف.لا يتم ترتيب الجدول على هذا النحو، ولا يكون نتيجة استعلام إلا إذا قمت بتحديد order by
استحضار الأرواح لأن الإجابات قديمة.
الاستفادة من LATERAL
الكلمة الرئيسية المقدمة في الصفحة 9.3
اليسار | الحق | صلة داخلية جانبي
سأشرح بمثال:
على افتراض أن لديك جدول "جهات الاتصال".
الآن تحتوي جهات الاتصال على وحدات تنظيمية.
يمكن أن يكون لديهم وحدة تنظيمية واحدة في وقت ما، لكن N OUs في N نقطة زمنية.
الآن، إذا كان عليك الاستعلام عن جهات الاتصال والوحدة التنظيمية في فترة زمنية (ليس تاريخ تقرير، ولكن نطاق تاريخ)، يمكنك زيادة عدد السجلات بمقدار N-fold إذا قمت للتو بربط يسار.
لذا، لعرض الوحدة التنظيمية، تحتاج فقط إلى الانضمام إلى الوحدة التنظيمية الأولى لكل جهة اتصال (حيث يكون ما يجب أن يكون أولاً معيارًا عشوائيًا - عند أخذ القيمة الأخيرة، على سبيل المثال، تكون هذه مجرد طريقة أخرى لقول القيمة الأولى عند الفرز بترتيب التاريخ التنازلي).
في SQL-server، يمكنك استخدام التطبيق المتقاطع (أو بالأحرى التطبيق الخارجي لأننا نحتاج إلى صلة يسارية)، والتي ستستدعي دالة ذات قيمة جدول في كل صف يجب عليه الانضمام إليه.
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
-- CROSS APPLY -- = INNER JOIN
OUTER APPLY -- = LEFT JOIN
(
SELECT TOP 1
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(@in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(@in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
) AS FirstOE
في PostgreSQL، بدءًا من الإصدار 9.3، يمكنك فعل ذلك أيضًا - فقط استخدم LATERAL
الكلمة الرئيسية لتحقيق نفس الشيء:
SELECT * FROM T_Contacts
--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989
LEFT JOIN LATERAL
(
SELECT
--MAP_CTCOU_UID
MAP_CTCOU_CT_UID
,MAP_CTCOU_COU_UID
,MAP_CTCOU_DateFrom
,MAP_CTCOU_DateTo
FROM T_MAP_Contacts_Ref_OrganisationalUnit
WHERE MAP_CTCOU_SoftDeleteStatus = 1
AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID
/*
AND
(
(__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo)
AND
(__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom)
)
*/
ORDER BY MAP_CTCOU_DateFrom
LIMIT 1
) AS FirstOE
حاول استخدام قاعدة استقامة في جملة ON.مثال مجردة: giveacodicetagpre.