嗨,我有一张桌子,当我查询一行时,我想知道特定数据出现在哪一列
TABLE
| A1 | A2 | A3 | A4 | A5 | ID |
QA W E R T 1
Y U I QA O 2
G H QA U T 3
例如,当我查询ID = 1的表时,我想知道发生在哪一列QA及其之前的所有列的情况下,单行中的数据将永远不会出现两次。
示例
Select * from table where ID=1
| A1 | ID |
QA 1
Select * from table where ID=2
| A1 | A2 | A3 | A4 | ID |
Y U I QA 2
我正在考虑为每一列使用5次case语句,但是我不知道如何在case语句内的THEN子句之后创建一个不同的select语句。
select case when A3 = 'QA' then select A1,A2,A3 from table where ID = 1)
? 谢谢
答案 0 :(得分:1)
有两种选择。本质上,您需要取消透视列,以便获取值。而且,您可以使用CTE过滤所需结果的结果。您可以使用T-SQL的UNPIVOT
或CROSS APPLY
(这可能会更快,并且可能会提供更简洁的查询计划)。
提供您的数据:
交叉应用示例:
; WITH myList AS (
SELECT t1.ID, ca.ColName, ca.Val
, ROW_NUMBER() OVER (PARTITION BY t1.ID ORDER BY ca.ColName) AS rn
FROM t1
CROSS APPLY (
VALUES
('Row_1', A1)
, ('Row_2', A2)
, ('Row_3', A3)
, ('Row_4', A4)
, ('Row_5', A5)
) ca(ColName, Val)
WHERE t1.ID = 2
)
, myPicks AS (
SELECT ID, ColName, Val, rn
FROM myList
WHERE Val = 'QA'
)
SELECT l.ID, l.ColName, l.Val
FROM myList l
INNER JOIN myPicks p ON l.ID = p.ID
AND l.rn <= p.rn
UNPIVOT示例:
; WITH myList AS (
SELECT unpiv.ID, unpiv.ColName, unpiv.Val
, ROW_NUMBER() OVER (PARTITION BY unpiv.ID ORDER BY unpiv.ColName) AS rn
FROM t1
UNPIVOT
(
Val
FOR ColName IN ( A1, A5, A3, A2, A4 )
) unpiv
WHERE unpiv.ID = 2
)
, myPicks AS (
SELECT ID, ColName, Val, rn
FROM myList
WHERE Val = 'QA'
)
SELECT l.ID, l.ColName, l.Val
FROM myList l
INNER JOIN myPicks p ON l.ID = p.ID
AND l.rn <= p.rn
...会给你...
ID ColName Val
2 A1 Y
2 A2 U
2 A3 I
2 A4 QA
这会将您的数据放入行中,这可能更易于使用编程语言进行操作,从而重新定义所需的方式。我不太确定您打算如何使用此代码或C#将如何使用它。这可能会改变实现它的最佳方式。
无论如何,不一定要保证SQL中的列列表会按特定顺序返回,并且如前所述,不应依赖列顺序。 PIVOT
/ UNPIVOT
的当前行为当前将按照您在IN
子句中放置的顺序对“列”进行排序,但这不是文档记录的行为,可以在任何更新时更改。在SQL中最可靠的排序方式是使用ORDER BY
子句。您可以为要取消透视的列添加别名(但需要更多工作),也可以仅将别名分配为CROSS APPLY
中的值之一。
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=2ee6086ef661901542ba4d7a6b20181f