英文:
How to summarize a set of rows and set a boolean based on a primary key and get a result in SQL
问题
I have 3 rows having the same key, I need to return "NO" if they don't contain the same value for all the rows having the same key.
在以下表格中,如果编号为999的记录具有相同的Val值,则其Bool值应为"No"。如果相同编号的值不同,则Bool应为"Yes"。
对于编号538,Val的值为0,30,0,因此Bool为"Yes"。
对于编号422,Val的值为30,30,30,因此Bool为"No"。
解决方案我尝试过:
SELECT [No], [Name], Mat, val,
CASE WHEN COUNT(*) OVER (PARTITION BY No) =
COUNT(Mat) OVER (PARTITION BY No)
AND MAX(val) OVER (PARTITION BY No) =
MIN(val) OVER (PARTITION BY No)
THEN 'No'
WHEN COUNT(Mat) OVER (PARTITION BY No) > 0
THEN 'Yes'
END AS Bool
FROM personal_table
如果使用以下查询,可以获得所需结果,但我不确定我打算使用的逻辑是否正确:
SELECT [No], [Name], Mat, val,
CASE WHEN MAX(val) OVER (PARTITION BY No) =
MIN(val) OVER (PARTITION BY No)
THEN 'No'
WHEN COUNT(Mat) OVER (PARTITION BY No) > 0
THEN 'Yes'
END AS Bool
FROM personal_table
谢谢您。
英文:
I have 3 rows having same key, I need to return as 'NO' if it doesnt contain the same value for all the rows having same key.
In this below table, The bool value for No 999 shoud be "No" as the Val for this records having the No 999 is same. The bool should be "Yes" if the value for that same No key has different value.
For 538 the val has 0,30,0 so the bool is "Yes"
For 422 the val has 30,30,30 so the bool is "No"
No | Name | Mat | Val | Bool |
---|---|---|---|---|
999 | AURO | NULL | 0 | Yes |
999 | AURO | 49790 | 0 | Yes |
999 | AURO | 53383 | 0 | Yes |
422 | BIO | 87103 | 30 | No |
422 | BIO | 87047 | 30 | No |
422 | BIO | 87100 | 30 | No |
538 | NOVA | 57819 | 0 | Yes |
538 | NOVA | 57850 | 30 | Yes |
538 | NOVA | 57788 | 0 | Yes |
Solution i tried:
SELECT [No], [Name],Mat, val,
CASE WHEN COUNT(*) OVER (PARTITION BY No) =
COUNT(Mat) OVER (PARTITION BY No)
AND MAX(val) OVER (PARTITION BY No) =
MIN(val) OVER (PARTITION BY No)
THEN 'No'
WHEN COUNT(Mat) OVER (PARTITION BY No) > 0
THEN 'Yes'
END AS Bool
FROM personal_table
Getting desired result if i use the below query but i am not sure the logic i am intended to use is correct or not
SELECT [No], [Name],Mat, val,
CASE WHEN MAX(val) OVER (PARTITION BY No) =
MIN(val) OVER (PARTITION BY No)
THEN 'No'
WHEN COUNT(Mat) OVER (PARTITION BY No) > 0
THEN 'Yes'
END AS Bool
FROM personal_table
Thank You
答案1
得分: 1
只需比较 MIN
与 MAX
。您需要考虑空值。
您可以使用新的 IS DISTINCT FROM
进行可空比较
SELECT
[No],
Name,
Mat,
val,
CASE WHEN
MAX(val) OVER (PARTITION BY No) IS DISTINCT FROM
MIN(val) OVER (PARTITION BY No)
THEN 'Yes'
ELSE 'No'
END AS Bool
FROM personal_table;
或在较旧的版本中使用
CASE WHEN
ISNULL(MAX(val) OVER (PARTITION BY No), 0) =
ISNULL(MIN(val) OVER (PARTITION BY No), 0)
英文:
Just compare the MIN
with the MAX
. You need to take into account nulls.
You can use the new IS DISTINCT FROM
for a nullable compare
SELECT
[No],
Name,
Mat,
val,
CASE WHEN
MAX(val) OVER (PARTITION BY No) IS DISTINCT FROM
MIN(val) OVER (PARTITION BY No)
THEN 'Yes'
ELSE 'No'
END AS Bool
FROM personal_table;
Or on older versions use
CASE WHEN
ISNULL(MAX(val) OVER (PARTITION BY No), 0) =
ISNULL(MIN(val) OVER (PARTITION BY No), 0)
答案2
得分: -1
I'd do it with a subjoin against the aggregated set:
;WITH cte AS (
SELECT *
FROM (
VALUES (999, N'AURO', N'NULL', 0, N'Yes')
, (999, N'AURO', N'49790', 0, N'Yes')
, (999, N'AURO', N'53383', 0, N'Yes')
, (422, N'BIO', N'87103', 30, N'No')
, (422, N'BIO', N'87047', 30, N'No')
, (422, N'BIO', N'87100', 30, N'No')
, (538, N'NOVA', N'57819', 0, N'Yes')
, (538, N'NOVA', N'57850', 30, N'Yes')
, (538, N'NOVA', N'57788', 0, N'Yes')
) t (No,Name,Mat,Val,Bool)
)
SELECT c.NO, c.Name, c.Mat, c.Val
, CASE WHEN valcount = 1 THEN 'No' ELSE 'Yes' END
FROM cte c
INNER JOIN (
SELECT count(DISTINCT val) AS valCount
, NO
FROM cte c2
GROUP BY no
) x
ON x.NO = c.No
Basically, you calculate the aggregate parts and then join it back to check if all values are distinct. Same can be achieved by a subquery:
;WITH cte AS (
SELECT *
FROM (
VALUES (999, N'AURO', N'NULL', 0, N'Yes')
, (999, N'AURO', N'49790', 0, N'Yes')
, (999, N'AURO', N'53383', 0, N'Yes')
, (422, N'BIO', N'87103', 30, N'No')
, (422, N'BIO', N'87047', 30, N'No')
, (422, N'BIO', N'87100', 30, N'No')
, (538, N'NOVA', N'57819', 0, N'Yes')
, (538, N'NOVA', N'57850', 30, N'Yes')
, (538, N'NOVA', N'57788', 0, N'Yes')
) t (No,Name,Mat,Val,Bool)
)
SELECT c.NO, c.Name, c.Mat, c.Val
, CASE WHEN (SELECT count(DISTINCT val) AS valCount FROM cte c2 where c2.NO = c.NO) = 1 THEN 'No' ELSE 'Yes' END
FROM cte c
英文:
I'd do it with a subjoin against the aggregated set:
;WITH cte AS (
SELECT *
FROM (
VALUES (999, N'AURO', N'NULL', 0, N'Yes')
, (999, N'AURO', N'49790', 0, N'Yes')
, (999, N'AURO', N'53383', 0, N'Yes')
, (422, N'BIO', N'87103', 30, N'No')
, (422, N'BIO', N'87047', 30, N'No')
, (422, N'BIO', N'87100', 30, N'No')
, (538, N'NOVA', N'57819', 0, N'Yes')
, (538, N'NOVA', N'57850', 30, N'Yes')
, (538, N'NOVA', N'57788', 0, N'Yes')
) t (No,Name,Mat,Val,Bool)
)
SELECT c.NO, c.Name, c.Mat, c.Val
, CASE WHEN valcount = 1 THEN 'No' ELSE 'Yes' END
FROM cte c
INNER JOIN (
SELECT count(DISTINCT val) AS valCount
, NO
FROM cte c2
GROUP BY no
) x
ON x.NO = c.No
Basically, you calculate the aggregate parts and then join it back to check if all values are distinct. Same can be achieved by a subquery:
;WITH cte AS (
SELECT *
FROM (
VALUES (999, N'AURO', N'NULL', 0, N'Yes')
, (999, N'AURO', N'49790', 0, N'Yes')
, (999, N'AURO', N'53383', 0, N'Yes')
, (422, N'BIO', N'87103', 30, N'No')
, (422, N'BIO', N'87047', 30, N'No')
, (422, N'BIO', N'87100', 30, N'No')
, (538, N'NOVA', N'57819', 0, N'Yes')
, (538, N'NOVA', N'57850', 30, N'Yes')
, (538, N'NOVA', N'57788', 0, N'Yes')
) t (No,Name,Mat,Val,Bool)
)
SELECT c.NO, c.Name, c.Mat, c.Val
, CASE WHEN (SELECT count(DISTINCT val) AS valCount FROM cte c2 where c2.NO = c.NO) = 1 THEN 'No' ELSE 'Yes' END
FROM cte c
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论