如何总结一组行,并根据主键设置布尔值,并在SQL中获得结果

huangapple go评论59阅读模式
英文:

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

只需比较 MINMAX。您需要考虑空值。

您可以使用新的 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

huangapple
  • 本文由 发表于 2023年5月22日 23:08:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76307563.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定