2017-02-14 16 views
13

Mam następujące zapytanie:Usuń zduplikowane dane z wyników zapytania

select 
    C.ClientID, 
    C.FirstName + ' ' + C.LastName as ClientName, 
    CAST(V.StartDate as date) as VisitDate, 
    count(*) as 'Number of Visits' 
from 
    Visit V 
Inner Join Client C on 
    V.ClientID = C.ClientID 
group by 
    C.ClientID, 
    C.FirstName + ' ' + C.LastName, 
    CAST(V.StartDate as date) 
having 
    count(*) > 3 
order by 
    C.ClientID, 
    CAST(V.StartDate as date) 

co daje następujące wyniki (nazwy są fałszywe w przypadku gdy ktoś zastanawia)

ClientID ClientName   VisitDate  Number of Visits 
75   Kay Taylor   2016-06-07  4 
372   Moses Mcgowan  2016-09-03  4 
422   Raven Mckay   2016-03-11  4 
422   Raven Mckay   2016-06-14  4 
679   Ulysses Booker  2016-01-09  4 
696   Timon Turner  2016-07-06  4 
1063  Quyn Wall   2016-06-25  4 
1142  Garth Moran   2016-11-20  4 
1142  Garth Moran   2016-11-21  4 
1563  Hedley Gutierrez 2016-01-07  4 
1563  Hedley Gutierrez 2016-01-17  4 
1563  Hedley Gutierrez 2016-01-21  4 
1563  Hedley Gutierrez 2016-01-27  4 
1563  Hedley Gutierrez 2016-01-28  4 
1563  Hedley Gutierrez 2016-01-30  4 
1563  Hedley Gutierrez 2016-02-27  4 
1563  Hedley Gutierrez 2016-03-26  4 
1563  Hedley Gutierrez 2016-04-06  4 
1563  Hedley Gutierrez 2016-04-09  4 
1563  Hedley Gutierrez 2016-04-22  4 
1563  Hedley Gutierrez 2016-05-06  4 
1563  Hedley Gutierrez 2016-05-26  4 
1563  Hedley Gutierrez 2016-06-02  4 
1563  Hedley Gutierrez 2016-07-14  4 
1563  Hedley Gutierrez 2016-07-29  4 
1563  Hedley Gutierrez 2016-08-09  7 
1563  Hedley Gutierrez 2016-09-01  4 
1563  Hedley Gutierrez 2016-09-23  4 
1563  Hedley Gutierrez 2016-12-07  4 
1636  Kiara Lowery  2016-01-12  4 
2917  Cynthia Carr  2016-06-21  4 
2917  Cynthia Carr  2016-10-21  4 
3219  Alan Monroe   2016-01-02  4 
3219  Alan Monroe   016-02-27  4 
3219  Alan Monroe   2016-09-01  5 
4288  Natalie Mitchell 2016-03-19  4 

Jak mogę uzyskać wyniki wyświetlić tylko ClientID i ClientName raz, więc wyniki są takie?

ClientID ClientName   VisitDate  Number of Visits 
75   Kay Taylor   2016-06-07  4 
372   Moses Mcgowan  2016-09-03  4 
422   Raven Mckay   2016-03-11  4 
           2016-06-14  4 
679   Ulysses Booker  2016-01-09  4 
696   Timon Turner  2016-07-06  4 
1063  Quyn Wall   2016-06-25  4 
1142  Garth Moran   2016-11-20  4 
           2016-11-21  4 
1563  Hedley Gutierrez 2016-01-07  4 
           2016-01-17  4 
           2016-01-21  4 
           2016-01-27  4 
           2016-01-28  4 
           2016-01-30  4 
           2016-02-27  4 
           2016-03-26  4 
           2016-04-06  4 
           2016-04-09  4 
           2016-04-22  4 
           2016-05-06  4 
           2016-05-26  4 
           2016-06-02  4 
           2016-07-14  4 
           2016-07-29  4 
           2016-08-09  7 
           2016-09-01  4 
           2016-09-23  4 
           2016-12-07  4 
1636  Kiara Lowery  2016-01-12  4 
2917  Cynthia Carr  2016-06-21  4 
           2016-10-21  4 
3219  Alan Monroe   2016-01-02  4 
3219       016-02-27  4 
           2016-09-01  5 
4288  Natalie Mitchell 2016-03-19  4 
+0

Nie powinieneś używać sql do tego – HoneyBadger

+0

Zrób to w swoim kodzie aplikacji. – GurV

+0

Zgadzam się z HB, jest to lepiej obsługiwane w warstwie prezentacji. Narzędzia do raportowania wykonają to automatycznie z odpowiednim ustawieniem. –

Odpowiedz

11

W rzeczywistości nie chodzi o usuwanie duplikatów, ale ich nie wyświetlanie.

W tym celu można wykorzystać do CASE oświadczenie z ROW_NUMBER() i pokazać wartość na 1. rzędu i ukazać zarówno NULL lub '' na ELSE Branch (inne wiersze):

select 
    CASE 
     WHEN ROW_NUMBER() OVER (PARTITION BY C.ClientID ORDER BY CAST(V.StartDate as date) ASC) = 1 
      THEN C.ClientID 
     ELSE NULL 
    END as ClientID, 
    CASE 
     WHEN ROW_NUMBER() OVER (PARTITION BY C.ClientID ORDER BY CAST(V.StartDate as date) ASC) = 1 
      THEN C.FirstName + ' ' + C.LastName 
     ELSE NULL 
    END as ClientName, 
    CAST(V.StartDate as date) as VisitDate, 
    count(*) as 'Number of Visits' 
from 
    Visit V 
Inner Join Client C on 
    V.ClientID = C.ClientID 
group by 
    C.ClientID, 
    C.FirstName + ' ' + C.LastName, 
    CAST(V.StartDate as date) 
having 
    count(*) > 3 
order by 
    C.ClientID, 
    CAST(V.StartDate as date) 
0

Możesz to rozwiązać za pomocą GROUP BY, grupując według (ClientID, VisitDate).

Zobacz odpowiedzi 1097 tutaj: Using group by on multiple columns

Uwaga: w zamówieniu nie jest konieczne stosowanie CAST(V.StartDate as date) można użyć VisitDate ponieważ istnieje w SELECT: ... CAST(V.StartDate as date) as VisitDate,

EDIT: Spróbuj tego:

SELECT 
    C.ClientID, 
    C.FirstName + ' ' + C.LastName as ClientName, 
    CAST(V.StartDate as date) as VisitDate, 
    count(*) as 'Number of Visits' 
from 
    Visit V 
Inner Join Client C on 
    V.ClientID = C.ClientID 
group by 
    (C.ClientID, VisitDate) 
having 
    count(*) > 3 
order by 
    C.ClientID, 
    VisitDate 
+0

Jak to pomoże? Sortowanie w kolumnie varchar może rzeczywiście prowadzić do sortowania nieparzystego, zależy to od formatu, w jakim znajduje się data. Jeśli chcesz sortować według daty, rzutowanie na datę może mieć znaczenie. – HoneyBadger

+0

Nie jest to tym, o co w ogóle poproszono. Pytanie jest pokazanie nazwy i id tylko dla jednego rekordu i pozostawienie pustego dla pozostałych wierszy o tej samej nazwie/id – HoneyBadger

+0

Ok. Następnie myślę, że musisz użyć konkatenacji ciągów dla kolumn VisitDate i Liczba odwiedzin. Po tym możesz podzielić każdą wartość w różnych wierszach. Zobacz: [link] https://www.codeproject.com/articles/691102/string-aggregation-in-the-world-of-sql-server [/ link] -http: //stackoverflow.com/questions/17591490/how-to-make-a-query-with-group-concat-in-sql-server –

3

Try This :

DECLARE @Table TABLE (ClientId NVARCHAR(5), ClientName NVARCHAR(6), VisitDate DATE, NumOfVisits INT) 

INSERT INTO @Table VALUES ('75' , 'A_NAME' , '2016-06-07' , '4'),('372' , 'B_NAME' , '2016-09-03' , '4'), 
    ('422' , 'C_NAME' , '2016-03-11' , '4'),('500' , 'D_NAME' , '2016-03-15' , '4'), 
    ('500' , 'D_NAME' , '2016-03-19' , '4'),('500' , 'D_NAME' , '2016-03-20' , '4'), 
    ('500' , 'D_NAME' , '2016-07-15' , '4'),('500' , 'D_NAME' , '2016-09-13' , '4'), 
    ('600' , 'E_NAME' , '2016-03-19' , '4'),('600' , 'E_NAME' , '2016-03-20' , '4'), 
    ('600' , 'E_NAME' , '2016-07-15' , '4'),('600' , 'E_NAME' , '2016-09-13' , '4') 

;WITH A AS (
SELECT ROW_NUMBER() OVER(PARTITION BY ClientID ORDER BY ClientID) row_id,* FROM (

        ----------------------------------------- 
SELECT * FROM @Table --- replace this line with your query---- 
        ----------------------------------------- 


) Main_Result) SELECT ISNULL(BB.ClientID,'')ClientID,ISNULL(BB.ClientName,'')ClientName,AA.VisitDate,AA.NumOfVisits 
FROM A AA LEFT JOIN (SELECT * FROM A BB WHERE BB.row_id=1) BB ON AA.ClientID = BB.ClientID AND AA.row_id =BB.row_id 
      ORDER BY CONVERT(INT,AA.ClientID) 

Mam nadzieję, że to pomoże. :)

możesz wykonać to bezpośrednio, aby uzyskać przykładowy wynik z przykładowych danych. :)

0

Mam nadzieję, że poniższe zapytanie byłoby zrobić .... :)

WITH CTE AS 
(
select top 100 percent 
    cast(C.ClientID as nvarchar(255)) as ClientID, 
    C.FirstName + ' ' + C.LastName as ClientName, 
    CAST(V.StartDate as date) as VisitDate, 
    count(*) as 'Number of Visits', 
    row_number() over (partition by C.ClientID,C.FirstName + ' ' + C.LastName ORDER BY CAST(V.StartDate as date)) as rw_num 
from 
    Visit V 
Inner Join Client C on 
    V.ClientID = C.ClientID 
group by 
    C.ClientID, 
    C.FirstName + ' ' + C.LastName, 
    CAST(V.StartDate as date) 
having 
    count(*) > 3 
order by 
    min(C.ClientID), 
    min(CAST(V.StartDate as date)) 

) 

select case 
     when rw_num<>1 then '' else ClientID end as ClientID, 
     case 
     when rw_num<>1 then '' else ClientName end as ClientName, 
     VisitDate, [Number of Visits] 
from CTE 

Wynik:

enter image description here

mojego testu Dane w tabelach moich testów:

enter image description here

0

Chciałbym użyć początkowego zapytania jako CTE lub podkwerendy do zastąpienia #TMP_DATA. Poniżej przedstawiam, jak to zrobić. Korzystanie z CASE z funkcją prowadzić do ustalenia, czy mają być wyświetlane dane w ClientID i clientname:

SELECT 
CASE WHEN CAST(LAG(T.ClientID,1,'') OVER (PARTITION BY T.ClientID ORDER BY T.ClientID,T.VisitDate) AS VARCHAR) = T.ClientID THEN '' ELSE CAST(T.ClientID AS VARCHAR) END AS ClientID, 
CASE WHEN LAG(T.ClientName,1,'') OVER (PARTITION BY T.ClientID ORDER BY  T.ClientID,T.VisitDate) = T.ClientName THEN '' ELSE T.ClientName END ClientName, 
T.VisitDate, 
T.[Number of Visits] 
FROM #TMP_DATA AS T 

zestaw wyników jest: ! https://i.stack.imgur.com/MBfEn.png