标识组在多个列中具有相同的值 SQL
Identifying groups have have same values across multiple columns SQL
我想弄清楚如何编写一个 SQL 查询来识别 table 中的一个组,该组在多个列的组中的记录中包含相同的值。
例如,给定以下示例 table:
在这种情况下,我希望确定所有试验的起点和终点都相同的名字。根据数据,只有 James 和 Frank 符合此标准。我不打算过滤和获取查询输出,这些查询输出只会给我所有带有“是”或“否”的组。我确实希望查询输出带有适当标记的组的整个 table。怎么办?
以下是我的全部资料。我确实看到,当我分组时,在感兴趣的列中显示所有相同值的组确实会合并为一组。但是,如果我放入一个新组,其中有多行(试验),其中每个试验可能具有相同的起点和终点,但该组的不同试验不是相同的点,那么实际上该组应该产生“否”甚至如果每个单独的试验显示相同的起点和终点。
CREATE TABLE Trial
(Name nvarchar(100),
Trial nvarchar(10),
Start nvarchar(100),
[End] nvarchar(100))
INSERT INTO Trial
VALUES
('Julie', 'A', 'Ranch St', 'Ranch St'),
('Julie', 'B', 'Ranch St', 'North Blvd'),
('James', 'A', 'Deer Rd', 'Deer Rd'),
('James', 'B', 'Deer Rd', 'Deer Rd'),
('Emily', 'A', 'Oak St', 'Oak St'),
('Emily', 'B', 'Oak St', 'Elm Rd'),
('Frank', 'A', 'Main Ave', 'Main Ave'),
('Frank', 'B', 'Main Ave', 'Main Ave'),
('Frank', 'C', 'Main Ave', 'Main Ave'),
('Jeff', 'A', 'Main Ave', 'Main Ave'),
('Jeff', 'B', 'Oak St', 'Oak St')
SELECT
a.[Name]
,CASE
WHEN a.[Start] = a.[END] THEN 'Yes' ELSE 'No'
END AS 'TrialChk'
FROM Trial AS a
GROUP BY a.[Name]
,a.[Start]
,a.[End]
ORDER BY Name ASC;
我在上面的示例 table 中没有 Jeff 试验,但 Jeff 会为每个试验给出“是”,但由于所有点都不相同,因此小组的输出应该是“否”。
您可以试试窗口函数Row_Number()
,如下图:
Create table MyTable (Name varchar(50),
Trial Char(1),
Start Varchar(20),
[End] Varchar(20))
Insert into MyTable Values
('Julie', 'A', 'Ranch St', 'Ranch St'),
('Julie', 'B', 'Ranch St', 'North Blvd'),
('James', 'A', 'Deer Rd', 'Deer Rd'),
('James', 'B', 'Deer Rd', 'Deer Rd')
;with cte as (Select name
,trial
,start
,[End]
,Row_number() Over(Partition By [Start], [End] order by [Start], [End]) as SrNo
From MyTable
)
Select
name, trial, start, [End], 'Yes' as [Expected Output]
from cte where name in ( Select name from cte where SrNo > 1)
union all
Select
name, trial, start, [End], 'No' as [Expected Output]
from cte where name not in (Select name from cte where SrNo > 1)
order by name
检查给定查询
DECLARE @Counter int
DECLaRE @CMS_Query varchar(MAX)
DECLARE @total_Row int
DECLARE Cur_1 CURSOR FOR select Name from Trial group by Name
Create Table #MainTrial(
[Name] varchar(MAX),
Trial varchar(MAX),
[Start] varchar(MAX),
[END] varchar(MAX),
[TrialChk] varchar(3)
)
OPEN Cur_1
DECLARE @Name varchar(MAX)
FETCH NEXT FROM Cur_1 INTO @Name
WHILE (@@FETCH_STATUS = 0)
Begin
SELECT a.[Name],Trial,Start,[End],CASE WHEN a.[Start] = a.[END] THEN 'Yes' ELSE 'No'END AS 'TrialChk' into #Trial1 FROM Trial AS a where Name = @Name
select @total_Row = count(*) from #Trial1
select @Counter = COUNT(*) from #Trial1 where TrialChk = 'Yes'
IF @total_Row != @Counter
BEGIN
UPDATE #Trial1 SET TrialChk = 'No' where [Name] = @Name
END
insert into #MainTrial select * from #Trial1
DROP Table #Trial1
FETCH NEXT FROM Cur_1 INTO @Name
END
CLOSE Cur_1
DEALLOCATE Cur_1
select * from #MainTrial
drop table #MainTrial
只需将 case
与 window 函数一起使用:
select t.*,
(case when min(start) over (partition by name) = max(start) over (partition by name) and
min(end) over (partition by name) = max(end) over (partition by name) and
start = end
then 'Yes' else 'No'
end) as flag
from trial t;
Here 是一个 db<>fiddle.
注意:end
是一个非常糟糕的列名称,因为它是 SQL 关键字。
如果您 GROUP BY Name
并计算 Start
和 End
的不同数量,就像这个查询一样:
SELECT Name, COUNT(DISTINCT Start) start_counter, COUNT(DISTINCT [End]) end_counter
FROM Trial
GROUP BY Name
你得到这些结果:
> Name | start_counter | end_counter
> :---- | ------------: | ----------:
> Emily | 1 | 2
> Frank | 1 | 1
> James | 1 | 1
> Jeff | 2 | 2
> Julie | 1 | 2
所以你可以将上面的查询加入你的 table 并设置 'Yes'
其中 2 个计数器都等于 1,否则设置 'No'
:
SELECT t.*,
CASE WHEN c.start_counter = 1 AND c.end_counter = 1 THEN 'Yes' ELSE 'No' END Result
FROM Trial t
INNER JOIN (
SELECT Name, COUNT(DISTINCT Start) start_counter, COUNT(DISTINCT [End]) end_counter
FROM Trial
GROUP BY Name
) c ON c.Name = t.Name
参见demo。
结果:
> Name | Trial | Start | End | Result
> :---- | :---- | :------- | :--------- | :-----
> Emily | A | Oak St | Oak St | No
> Emily | B | Oak St | Elm Rd | No
> Frank | A | Main Ave | Main Ave | Yes
> Frank | B | Main Ave | Main Ave | Yes
> Frank | C | Main Ave | Main Ave | Yes
> James | A | Deer Rd | Deer Rd | Yes
> James | B | Deer Rd | Deer Rd | Yes
> Jeff | A | Main Ave | Main Ave | No
> Jeff | B | Oak St | Oak St | No
> Julie | A | Ranch St | Ranch St | No
> Julie | B | Ranch St | North Blvd | No
我想弄清楚如何编写一个 SQL 查询来识别 table 中的一个组,该组在多个列的组中的记录中包含相同的值。
例如,给定以下示例 table:
在这种情况下,我希望确定所有试验的起点和终点都相同的名字。根据数据,只有 James 和 Frank 符合此标准。我不打算过滤和获取查询输出,这些查询输出只会给我所有带有“是”或“否”的组。我确实希望查询输出带有适当标记的组的整个 table。怎么办?
以下是我的全部资料。我确实看到,当我分组时,在感兴趣的列中显示所有相同值的组确实会合并为一组。但是,如果我放入一个新组,其中有多行(试验),其中每个试验可能具有相同的起点和终点,但该组的不同试验不是相同的点,那么实际上该组应该产生“否”甚至如果每个单独的试验显示相同的起点和终点。
CREATE TABLE Trial
(Name nvarchar(100),
Trial nvarchar(10),
Start nvarchar(100),
[End] nvarchar(100))
INSERT INTO Trial
VALUES
('Julie', 'A', 'Ranch St', 'Ranch St'),
('Julie', 'B', 'Ranch St', 'North Blvd'),
('James', 'A', 'Deer Rd', 'Deer Rd'),
('James', 'B', 'Deer Rd', 'Deer Rd'),
('Emily', 'A', 'Oak St', 'Oak St'),
('Emily', 'B', 'Oak St', 'Elm Rd'),
('Frank', 'A', 'Main Ave', 'Main Ave'),
('Frank', 'B', 'Main Ave', 'Main Ave'),
('Frank', 'C', 'Main Ave', 'Main Ave'),
('Jeff', 'A', 'Main Ave', 'Main Ave'),
('Jeff', 'B', 'Oak St', 'Oak St')
SELECT
a.[Name]
,CASE
WHEN a.[Start] = a.[END] THEN 'Yes' ELSE 'No'
END AS 'TrialChk'
FROM Trial AS a
GROUP BY a.[Name]
,a.[Start]
,a.[End]
ORDER BY Name ASC;
我在上面的示例 table 中没有 Jeff 试验,但 Jeff 会为每个试验给出“是”,但由于所有点都不相同,因此小组的输出应该是“否”。
您可以试试窗口函数Row_Number()
,如下图:
Create table MyTable (Name varchar(50),
Trial Char(1),
Start Varchar(20),
[End] Varchar(20))
Insert into MyTable Values
('Julie', 'A', 'Ranch St', 'Ranch St'),
('Julie', 'B', 'Ranch St', 'North Blvd'),
('James', 'A', 'Deer Rd', 'Deer Rd'),
('James', 'B', 'Deer Rd', 'Deer Rd')
;with cte as (Select name
,trial
,start
,[End]
,Row_number() Over(Partition By [Start], [End] order by [Start], [End]) as SrNo
From MyTable
)
Select
name, trial, start, [End], 'Yes' as [Expected Output]
from cte where name in ( Select name from cte where SrNo > 1)
union all
Select
name, trial, start, [End], 'No' as [Expected Output]
from cte where name not in (Select name from cte where SrNo > 1)
order by name
检查给定查询
DECLARE @Counter int
DECLaRE @CMS_Query varchar(MAX)
DECLARE @total_Row int
DECLARE Cur_1 CURSOR FOR select Name from Trial group by Name
Create Table #MainTrial(
[Name] varchar(MAX),
Trial varchar(MAX),
[Start] varchar(MAX),
[END] varchar(MAX),
[TrialChk] varchar(3)
)
OPEN Cur_1
DECLARE @Name varchar(MAX)
FETCH NEXT FROM Cur_1 INTO @Name
WHILE (@@FETCH_STATUS = 0)
Begin
SELECT a.[Name],Trial,Start,[End],CASE WHEN a.[Start] = a.[END] THEN 'Yes' ELSE 'No'END AS 'TrialChk' into #Trial1 FROM Trial AS a where Name = @Name
select @total_Row = count(*) from #Trial1
select @Counter = COUNT(*) from #Trial1 where TrialChk = 'Yes'
IF @total_Row != @Counter
BEGIN
UPDATE #Trial1 SET TrialChk = 'No' where [Name] = @Name
END
insert into #MainTrial select * from #Trial1
DROP Table #Trial1
FETCH NEXT FROM Cur_1 INTO @Name
END
CLOSE Cur_1
DEALLOCATE Cur_1
select * from #MainTrial
drop table #MainTrial
只需将 case
与 window 函数一起使用:
select t.*,
(case when min(start) over (partition by name) = max(start) over (partition by name) and
min(end) over (partition by name) = max(end) over (partition by name) and
start = end
then 'Yes' else 'No'
end) as flag
from trial t;
Here 是一个 db<>fiddle.
注意:end
是一个非常糟糕的列名称,因为它是 SQL 关键字。
如果您 GROUP BY Name
并计算 Start
和 End
的不同数量,就像这个查询一样:
SELECT Name, COUNT(DISTINCT Start) start_counter, COUNT(DISTINCT [End]) end_counter
FROM Trial
GROUP BY Name
你得到这些结果:
> Name | start_counter | end_counter
> :---- | ------------: | ----------:
> Emily | 1 | 2
> Frank | 1 | 1
> James | 1 | 1
> Jeff | 2 | 2
> Julie | 1 | 2
所以你可以将上面的查询加入你的 table 并设置 'Yes'
其中 2 个计数器都等于 1,否则设置 'No'
:
SELECT t.*,
CASE WHEN c.start_counter = 1 AND c.end_counter = 1 THEN 'Yes' ELSE 'No' END Result
FROM Trial t
INNER JOIN (
SELECT Name, COUNT(DISTINCT Start) start_counter, COUNT(DISTINCT [End]) end_counter
FROM Trial
GROUP BY Name
) c ON c.Name = t.Name
参见demo。
结果:
> Name | Trial | Start | End | Result
> :---- | :---- | :------- | :--------- | :-----
> Emily | A | Oak St | Oak St | No
> Emily | B | Oak St | Elm Rd | No
> Frank | A | Main Ave | Main Ave | Yes
> Frank | B | Main Ave | Main Ave | Yes
> Frank | C | Main Ave | Main Ave | Yes
> James | A | Deer Rd | Deer Rd | Yes
> James | B | Deer Rd | Deer Rd | Yes
> Jeff | A | Main Ave | Main Ave | No
> Jeff | B | Oak St | Oak St | No
> Julie | A | Ranch St | Ranch St | No
> Julie | B | Ranch St | North Blvd | No