質問

次のクエリを持っています:

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'を持つ2つのエントリがある場合は、それぞれ'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
.

しかし、あなたは本当にグループごとの数に乗りたいですか?

Group毎の1行を、 "EsnsSalesOrderItems" を使用して、DISTINCT ONの1行を取得します。詳細な説明:

他のヒント

何かのようなもの:

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を選択します。テーブルの構造を投稿しなかったので、列名を「発明」しなければなりませんでした。定義できる列を使用できます。あなたに合った行の順序。

しかし、「最後の行」の概念を覚えておくことは、注文または行を指定した場合にのみ有効です。そのようなテーブルは順序付けられていない、 を指定しない限り、クエリ の結果は を指定しない限りです。

答えが古くなっているため、Necromancing。
pg 9.3 で導入されたLATERALキーワードを利用してください。

左|右へ内部結合

例で説明します。
テーブル「連絡先」があると仮定してください。
今すぐ連絡先には組織単位があります。
彼らは時点で1つのOUを持つことができますが、nは間に合います。

今、連絡先とOU (レポート日ではなく日付範囲ではありません)に照会する必要がある場合は、Nオフフォールドが行った場合にレコード数を増やすことができます。左に参加します。
それで、OUを表示するには、最初の連絡先について最初のOUに参加する必要があります(最後の値を取得するときは任意の基準です。たとえば、それは並べ替えたときに最初の値を任意の方法で言うだけです。降順で降順で)。

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句の副問合せを使用してみてください。抽象例:

SELECT 
    *
FROM table1
JOIN table2 ON table2.id = (
    SELECT id FROM table2 WHERE table2.table1_id = table1.id LIMIT 1
)
WHERE 
    ...
.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top