sql-server - 複数 - union all




サブクエリの最初の行にどのように参加すればよいですか? (4)

Carriersidと呼ばれるPRIMARY KEY持ってPRIMARY KEY

SELECT  i.[Invoice Number],
        c.[Carrier Name]
FROM    Invoice i
JOIN    Carriers c
ON      c.id = 
        (
        SELECT  TOP 1 ID
        FROM    Carriers ci
        WHERE   ci.InvoiceKey = i.InvoiceKey
        ORDER BY
                id -- or whatever
        )

私は、請求書のテーブルと関連するデータの子テーブルをキーで関連づけています。 特に、各請求書について、私は子テーブルの最初の関連する行だけに興味があります。 私はすべての請求書のキーの1つの関連する行が欲しい - 私はこれをどのように達成するのですか?

Select i.[Invoice Number],
       c.[Carrier Name]
From Invoice i
    Left Join Carriers c on i.[InvoiceKey] = c.[InvoiceKey]
Where -- what?

私は、意味的に言えば、 Top 1 c.CarrierName Group by InvoiceKeyコンセプトに似た何かを探しているとTop 1 c.CarrierName Group by InvoiceKey (T-SQLで可能だった場合は、そのコンセプトになります)。

サブクエリの左結合について考えましたが、それは効率的ではないようです。 誰でも効率的にこれを達成するためのT-SQLのやり方はありますか?

編集 :ごめんなさい、私はこれがSQL Server 2000だから言えて忘れてしまったので、現在のSQL Server 2005/2008の応答に対してupvotesを与えるつもりですが、私はそれを受け入れることができません。


これはあなたのもの(MySQLスタイル)とは若干異なる構文を使って私がやる方法ですが、あなたもそれをあなたのソリューションにも適用できると思います:

SELECT i.invoiceNumber, c.carrierName
FROM Invoice as i
LEFT JOIN Carriers as c ON (c.id = (SELECT id FROM Carriers WHERE invoiceKey = i.invoiceKey ORDER BY id LIMIT 1))

これは、請求書からのすべてのレコードを受け取り、キャリヤーからの1つ(またはゼロ)のレコードと結合します。具体的には、同じinvoiceKeyと最初のレコードのみを持つレコードです。

Carriers.invoiceKeyのインデックスを持っている限り、このクエリのパフォーマンスは許容されるはずです。

セバスチャン


そのような場合、私はここであなたの例に当てはめて説明し、以下で説明するデバイスを採用することがよくあります:

SELECT
  i.[Invoice Number],
  c.[Carrier Name]
FROM Invoice i
  INNER JOIN Carriers c ON i.InvoiceKey = c.InvoiceKey
  INNER JOIN (
    SELECT MIN(ID) AS ID
    FROM Carriers
    GROUP BY InvoiceKey
  ) c_top ON c.ID = c_top.ID

私は、これはQuassnoiが投稿したものと大体同じですが、私はそのようなSELECT TOPを使用しないようにしています。

Invoiceは、リンク式(この場合はInvoiceKeyに基づいてCarriersと結合されます。 今、 Carriersは同じInvoiceKeyに対して複数の行を持つことができるので、出力を制限する必要があります。 これは、派生テーブルを使用して行われます。

派生テーブルは、2つのテーブル( InvoiceKey )のリンクに使用されているのと同じ式に基づいて、Carrierの行をグループ化します。

別の方法があります。派生テーブルに参加する代わりに、同じ効果を持つIN (subquery)を使用できます。 つまり、完全なクエリは次のようになります。

SELECT
  i.[Invoice Number],
  c.[Carrier Name]
FROM Invoice i
  INNER JOIN Carriers c ON i.InvoiceKey = c.InvoiceKey
    AND c.ID IN (SELECT MIN(ID) FROM Carriers GROUP BY InvoiceKey)

;with cteRowNumber as (
    select c.InvoiceKey, c.[Carrier Name], ROW_NUMBER() over (partition by c.InvoiceKey order by c.[Carrier Name]) as RowNum
        from Carriers c
)
select i.[Invoice Number],
       rn.[Carrier Name]
    from Invoice i
        left join cteRowNumber rn
            on i.InvoiceKey = rn.InvoiceKey
                and rn.RowNum = 1






sql-server-2000