2017-01-11 5 views
0

私はLH1、LH2、LH3、RH1、 RH2、RH3のような複数のビット列を持つテーブルを持っています。 (私は右手、左目、右足、左足などと同じ方法)sql selectクエリの複数のビット値に基づいてコンマ区切り文字列を取得

Nowそれらのビット値に基づいて、コンマ区切り文字列を取得したいと思います。 Exapmle iF LH1,RH1,RH2 and LH3 are true then I want '1,3' as LH and '1,2' as RH.

IF LH3,RH1,RH2 and RH3 are true then I want '1' as LH and '1,2,3' as RH.

については

私は下のリンクを通過したが、それは

https://dba.stackexchange.com/questions/112408/join-with-comma-separated-values-in-sql-server

おかげ

+0

あなたは、MySQLとSQL-Serverデータベースの両方を使用していますか?それぞれのDBMSだけに親切にタグを付けない場合は、 – Viki888

+0

私はSQL Serverを使用しています。 – Hitesh

+0

列名は常に2文字と1つの数字ですか? – Shnugo

答えて

1

あなたのデザインがするたびに...オーケーではありません番号の列をのように追加する必要がありますこれは関連する子テーブルを泣かせます!しかし、それにもかかわらず、あなたは動的に適切な文を作成することができます。

この表はモックアップあなたのテーブル

CREATE TABLE Dummy(ID INT IDENTITY,ControlString VARCHAR(100),LH1 BIT,LH2 BIT,LH3 BIT,RH1 BIT,RH2 BIT); 
INSERT INTO Dummy VALUES 
('All True',1,1,1,1,1) 
,('All LH True',1,1,1,0,0) 
,('All RH True',0,0,0,1,1) 
,('LH1 and RH1',1,0,0,1,0) 
,('LH2,3 and RH1,2',0,1,1,1,1); 
GO 

あなたはこのだっ必要があると思い声明:

SELECT ID 
     ,ControlString 
     ,CASE WHEN LH1=1 THEN ',1' ELSE '' END+CASE WHEN LH2=1 THEN ',2' ELSE '' END+CASE WHEN LH3=1 THEN ',3' ELSE '' END AS [LH] 
     ,CASE WHEN RH1=1 THEN ',1' ELSE '' END+CASE WHEN RH2=1 THEN ',2' ELSE '' END AS [RH] 
FROM Dummy 

を--I」 メタデータを使用してすべての列の名前を検索し、文字列ベースの文を作成します。

DECLARE @cmd AS VARCHAR(MAX); 
WITH AllColumns AS 
(
    SELECT LEFT(COLUMN_NAME,2) AS Location 
      ,SUBSTRING(COLUMN_NAME,3,1000) AS Indx 
      ,COLUMN_NAME 
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='Dummy' AND LEN(COLUMN_NAME)=3 
) 
SELECT @cmd='SELECT ID,ControlString,' + STUFF(
(
    SELECT ',' + STUFF(
         ((SELECT '+CASE WHEN ' + grp.COLUMN_NAME + '=1 THEN '',' + grp.Indx + ''' ELSE '''' END' 
          FROM AllColumns AS grp 
          WHERE grp.Location=AllColumns.Location 
          FOR XML PATH('')) + ' AS ' + QUOTENAME(Location) 
         ),1,1,'' 
         ) 
    FROM AllColumns 
    GROUP BY Location 
    FOR XML PATH('') 
    ),1,1,'' 
) + ' FROM Dummy'; 

EXEC(@cmd); 
GO 

--cleanアップ

DROP TABLE Dummy; 

結果

ID ControlString LH  RH 
1 All True  ,1,2,3 ,1,2 
2 All LH True  ,1,2,3 
3 All RH True    ,1,2 
4 LH1 and RH1  ,1  ,1 
5 LH2,3 and RH1,2 ,2,3 ,1,2 
+0

ありがとう@ Shnugo。それは今働く – Hitesh

0

あなたのデータ構造ID「デ私の場合には有用ではありません常に後続の処理をより困難にする「標準化された」(または「ピボットされた」)。したがって、最初のステップは、次のステップをより簡単にするためにそのデータを「正規化」(または「ピボット解除」)することです。

これを実行するには、「unpivot」コマンドを使用する必要はありません。SQL Serverでは、最初の部分(以下のCTE)を達成するために、CRUSS APPLYとVALUESを使います。次に、 "FOR XML PATH"とSTUFF()を使用してカンマ区切りの文字列を実現します。

次のサンプルデータから:

CREATE TABLE Table1 
    ([id] int, [lh1] bit, [lh2] bit, [lh3] bit, [lh4] bit, [rh1] bit, [rh2] bit, [rh3] bit, [rh4] bit) 
; 

INSERT INTO Table1 
    ([id], [lh1], [lh2], [lh3], [lh4], [rh1], [rh2], [rh3], [rh4]) 
VALUES 
    (1001, 1, 0, 0, 0, 0, 0, 1, 0), 
    (1002, 0, 1, 0, 0, 1, 0, 0, 0), 
    (1003, 0, 0, 1, 0, 0, 1, 0, 0), 
    (1004, 0, 1, 0, 1, 0, 0, 1, 0), 
    (1005, 1, 0, 1, 0, 0, 1, 0, 1), 
    (1006, 0, 0, 0, 0, 1, 0, 1, 0), 
    (1007, 1, 0, 0, 1, 0, 0, 0, 0), 
    (1008, 0, 1, 1, 0, 1, 0, 0, 1) 
; 

してから、このクエリ:

;with CTE as (
     select 
       id, ca.colname, colvalue 
     from table1 
     cross apply (
       values 
        ('lh1',case when lh1 = 1 then 1 end) 
        , ('lh2',case when lh2 = 1 then 2 end) 
        , ('lh3',case when lh3 = 1 then 3 end) 
        , ('lh4',case when lh4 = 1 then 4 end) 
        , ('rh1',case when rh1 = 1 then 1 end) 
        , ('rh2',case when rh2 = 1 then 2 end) 
        , ('rh3',case when rh3 = 1 then 3 end) 
        , ('rh4',case when rh4 = 1 then 4 end) 
      ) ca (colname, colvalue) 
     where ca.colvalue IS NOT NULL 
     ) 
SELECT 
    t.id, l.h as lh, r.h as rh 
FROM table1 t 
CROSS APPLY (SELECT 
     STUFF((SELECT 
     ',' + CAST(cte.colvalue AS char(1)) 
     FROM cte 
     WHERE t.id = cte.id 
     AND cte.colname like 'lh%' 
     ORDER BY cte.colname 
     FOR xml PATH ('')) 
     , 1, 1, '')) AS l (h) 
CROSS APPLY (SELECT 
     STUFF((SELECT 
     ',' + CAST(cte.colvalue AS char(1)) 
     FROM cte 
     WHERE t.id = cte.id 
     AND cte.colname like 'rh%' 
     ORDER BY cte.colname 
     FOR xml PATH ('')) 
     , 1, 1, '')) AS r (h) 


     select 
       id, ca.colname, colvalue 
     from table1 
     cross apply (
       values 
        ('lh1',case when lh1 = 1 then 1 end) 
        , ('lh2',case when lh2 = 1 then 2 end) 
        , ('lh3',case when lh3 = 1 then 3 end) 
        , ('lh4',case when lh4 = 1 then 4 end) 
        , ('rh1',case when rh1 = 1 then 1 end) 
        , ('rh2',case when rh2 = 1 then 2 end) 
        , ('rh3',case when rh3 = 1 then 3 end) 
        , ('rh4',case when rh4 = 1 then 4 end) 
      ) ca (colname, colvalue) 
     where ca.colvalue IS NOT NULL 
     order by id, colname, colvalue 

あなたはこの結果を得る:

+----+------+------+------+ 
| | id | lh | rh | 
+----+------+------+------+ 
| 1 | 1001 | 1 | 3 | 
| 2 | 1002 | 2 | 1 | 
| 3 | 1003 | 3 | 2 | 
| 4 | 1004 | 2,4 | 3 | 
| 5 | 1005 | 1,3 | 2,4 | 
| 6 | 1006 | NULL | 1,3 | 
| 7 | 1007 | 1,4 | NULL | 
| 8 | 1008 | 2,3 | 1,4 | 
+----+------+------+------+ 
+0

OPはどの列が真であるかを知る必要があります。結果 '1,1'はこれを反映していません... – Shnugo

+0

はい、間違った例を使用しましたが、修正されました。 –

関連する問題