4

Oracle では、||を使用して、複数の列の個別の値の数を取得できます。オペレーター(とにかく、このフォーラムの投稿によると):

SELECT COUNT(DISTINCT ColumnA || ColumnB) FROM MyTable

SQL Server 2008 でこれを行う方法はありますか? グループ統計を返すために単一のクエリを実行しようとしていますが、それができないようです。

たとえば、クエリしようとしている値のテーブルを次に示します。

AssetId MyId    TheirId   InStock
328     10      10        1
328     20      20        0
328     30      30        0
328     40      10        0
328     10      10        0
328     10      10        0
328     10      10        0
328     10      10        0

AssetId #328 について、MyId 列と TheirId 列の一意の ID の総数( 4 = 10、20、30、40 ) と、 InStock列のゼロ以外の行の総数(1 ):

AssetId     TotalIds    AvailableIds
328         4           1

どういうわけかこの魔法を働かせる方法はありますか?

4

6 に答える 6

2

cross applyとを使用できますvalues

select T1.AssetId,
       count(distinct T2.ID) TotalIds,
       sum(case T2.InStock when 0 then 0 else 1 end) AvailableIds 
from YourTable as T1
  cross apply(values(T1.MyId, T1.InStock),
                    (T1.TheirId, 0)
             ) as T2(ID, InStock)
group by T1.AssetId  

SEデータ

またはunion all、サブクエリで a を実行できます。

select T.AssetId,
       count(distinct T.ID) TotalIds,
       sum(case T.InStock when 0 then 0 else 1 end) AvailableIds 
from (
     select AssetId, MyId as ID, InStock
     from YourTable
     union all
     select AssetID, TheirId, 0
     from YourTable
     ) as T
group by T.AssetId  
于 2012-08-12T09:54:45.670 に答える
1

私はそれがあなたにとって良い解決策だと思います

SELECT COUNT(*)
FROM (SELECT DISTINCT Column1, Column2 
      FROM MyTable) A
于 2012-08-12T08:07:54.863 に答える
1

Oracleの例に従って、値を連結することができます(これは、Oracleクエリが実行していることです)。最初に値を文字に変換する必要があります。

select AssetId,
       count(distinct cast(MyId as varchar(8000))+','+cast(TheirId as varchar(8000)
            ) totalIds,
       count(distinct case when inStock> 0
                           then cast(MyId as varchar(8000))+','+cast(TheirId as varchar(8000)
             end) as AvailableIds
from t
group by Assetid

サブクエリとして実行することもできます。

select AssetId, count(*) as TotalIds,
       sum(case when inStock > 0 then 1 else 0 end) as AvailableIds
from (select AssetId, myId, theirId, max(inStock) as inStock
      from t
      group by AssetId, myId, theirId
     ) a
group by AssetId

「理論的には」、2番目のアプローチはセットベースであるため、私は2番目のアプローチの方が好きです。ただし、いくつかの異なる変数で個別の組み合わせ列をカウントしようとしている場合は、文字列連結アプローチの方が実用的です。

于 2012-08-12T14:50:18.687 に答える
1

次のように結果を取得できます。

DECLARE @t TABLE (AssetId INT, MyId    INT, TheirId   INT, InStock INT)
INSERT @t
VALUES 
(328,10, 10,   1)
,(328,20, 20,   0)
,(328,30, 30,   0)
,(328,40, 10,   0)
,(328,10, 10,   0)
,(328,10, 10,   0)
,(328,10, 10,   0)
,(328,10, 10,   0)

;WITH a AS(
    SELECT  AssetId,
            COUNT(col) cnt
    FROM 
    (
            SELECT  MyId col, AssetId
            FROM    @t
            UNION
            SELECT  TheirId col, AssetId
            FROM    @t
    ) b
    GROUP BY AssetId
)

SELECT  a.AssetId,
        a.cnt TotalIds,
        SUM(CASE WHEN InStock <> 0 THEN 1 ELSE 0 END) AvailableIds
FROM    @t c
JOIN    a ON a.AssetId = c.AssetId
GROUP   BY a.AssetId, a.cnt

共通テーブル式 (コード ブロック) では、重複する値を破棄する演算子をWITH使用することで「一意性」が保証されるため、 のように使用する必要はありません。UNIONCOUNT(col)COUNT(DISTINCT col)

于 2012-08-12T07:55:40.440 に答える
0

を使用したくない場合はCTE's、次の解決策を使用してみてください。その要点は

  • 別のサブクエリTotalID'sでそれぞれのを選択しますAssetID
  • 別のサブクエリAvailableIDsでそれぞれのを選択しますAssetID
  • JOIN最終結果を生成するための両方のサブクエリの結果。

ステートメントはそのままで、テーブル全体で機能します。グループ全体に適切なwhere句を追加することで、単一のAssetIDの結果を取得できます。

SQLステートメント

SELECT  a.AssetId, t.TotalIDs, a.AvailableIDs
FROM    (
            SELECT  AssetID, TotalIDs = COUNT(*) 
            FROM    (
                        SELECT  AssetID 
                        FROM    MyTable 
                        GROUP BY 
                                MyId, TheirID, AssetID
                    ) t 
            GROUP BY 
                    AssetID
        ) AS t
        INNER JOIN (
            SELECT  AssetID, AvailableIDs = SUM(InStock) 
            FROM    MyTable 
            GROUP BY 
                    AssetID
        ) AS a ON a.AssetId = t.AssetId

テストスクリプト

;WITH MyTable (AssetId, MyId, TheirId, InStock) AS (
    SELECT * FROM (VALUES 
        (328, 10, 10, 1)
        , (328, 20, 20, 0)
        , (328, 30, 30, 0)
        , (328, 40, 10, 0)
        , (328, 10, 10, 0)
        , (328, 10, 10, 0)
        , (328, 10, 10, 0)
        , (328, 10, 10, 0)
        , (329, 10, 10, 0)
        , (329, 10, 20, 1)
    ) AS a (b, c, d, e)
)
SELECT  a.AssetId, t.TotalIDs, a.AvailableIDs
FROM    (
            SELECT  AssetID, TotalIDs = COUNT(*) 
            FROM    (
                        SELECT  AssetID 
                        FROM    MyTable 
                        GROUP BY 
                                MyId, TheirID, AssetID
                    ) t 
            GROUP BY 
                    AssetID
        ) AS t
        INNER JOIN (
            SELECT  AssetID, AvailableIDs = SUM(InStock) 
            FROM    MyTable 
            GROUP BY 
                    AssetID
        ) AS a ON a.AssetId = t.AssetId
于 2012-08-12T09:48:03.630 に答える
0

オプション1

select 
          AssetID, count(distinct MyId) As MyId, SUM(InStock) InStock
From T
Group By 
      AssetID

オプション #2 CTE なし

Select AssetID, count(MyId), sum(InStock) InStock From
(
    select 
            AssetID, MyId, SUM(InStock) InStock
    From MyTable
    Group By 
            AssetID, MyId
)K
Group by AssetID

オプション #3 CTE あり

;With Sub(AssetID, MyId, InStock)
As
(
    select 
            AssetID, MyId, SUM(InStock) InStock
    From MyTable
    Group By 
            AssetID, MyId
)

Select AssetID, count(MyId), sum(InStock) From
(
    Select * from Sub
)K
于 2012-08-12T09:19:47.680 に答える