簡體   English   中英

標識組在多個列中具有相同的值 SQL

[英]Identifying groups have have same values across multiple columns SQL

我試圖弄清楚如何編寫一個 SQL 查詢,該查詢將識別表中的一個組,該組在多列的組中的記錄中包含相同的值。

例如,給定以下示例表:

姓名 開始 結束 朱莉

在這種情況下,我希望確定所有試驗都具有相同起點和終點的名稱。 根據數據,只有 James 和 Frank 符合此標准。 我不希望過濾和獲取查詢 output,它只會給我所有組“是”或“否”。 我確實希望查詢 output 整個表,並帶有適當標記的組。 如何 go 關於這個?

以下是我所得到的。 我確實看到,當我分組時,在感興趣的列中顯示所有相同值的組確實會合並為一組。 但是,如果我加入一個新組,其中有多個行(試驗),其中每個試驗可能具有相同的起點和終點,但該組的不同試驗不是相同的點,那么實際上該組甚至應該產生“否”如果每個單獨的試驗顯示相同的起點和終點。

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;

我在上面的示例表中沒有 Jeff 試驗,但 Jeff 會為每個試驗給出“是”,但由於所有點都不相同,因此該組的 output 應該是“否”。

您可以嘗試窗口化的 function 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

在此處輸入圖像描述

window 函數的簡單用case

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;

是一個 db<>fiddle。

注意: end是一個非常糟糕的列名稱,因為它是一個 SQL 關鍵字。

如果您GROUP BY Name並計算StartEnd的不同數量,就像這個查詢一樣:

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

因此,您可以將上述查詢加入您的表並設置'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 

演示
結果:

> 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  

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM