Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Bagaimana cara menanyakan output ini di SQL server

Selamat siang,

Silakan periksa apakah solusi di bawah ini menyelesaikan semua kebutuhan Anda. Saya mengujinya dengan data Anda dan dengan beberapa baris lagi, tetapi selalu yang terbaik adalah memeriksa ulang. Sepintas sepertinya mengembalikan hasil yang diminta. Saya akan menambahkan beberapa penjelasan nanti

Kueri yang saya gunakan ini:

DECLARE @Date DATE = '2018-06-12';
with MyCTE as (
    SELECT 
        t.CustName,t.Country,t.RecordedTime,t.CurrNo, D = CONVERT(DATE, RecordedTime)
        ,RN_D = ROW_NUMBER() 
            OVER (partition by t.CustName order by t.CurrNo desc)
        ,RN = ROW_NUMBER() 
            OVER (partition by t.CustName order by t.CurrNo)
        ,RN_Old = ROW_NUMBER() 
            OVER (partition by t.CustName, (CASE WHEN CONVERT(DATE, RecordedTime) < @Date then 0 else 1 END) order by t.CurrNo desc)
        ,Cnt = COUNT(*) 
            OVER (partition by t.CustName)
        ,CntToday = COUNT(CASE WHEN CONVERT(DATE, RecordedTime) = @Date THEN 1 ELSE NULL END) 
            OVER (partition by t.CustName)
    FROM Test t
    where 
        -- returns rows untill current date
        CONVERT (DATE, RecordedTime) <= @Date 
        -- only if relevnat to current date
        and EXISTS (
            SELECT * FROM test t0 
            where CONVERT (DATE, RecordedTime) = @Date and t0.CustName = t.CustName
        )
)
,MyCTE2 as (
    select
        CustName, Country, RecordedTime, D, CurrNo, RN_D, RN, Cnt, t2.c, History, CntToday, RN_Old
    from MyCTE t1
    left JOIN (select * from (values(1, 'NEW'),(1, 'BEFORE')) t2(c, History) ) t2 
        on t1.CurrNo = t2.c
            and CntToday > 1
            and D = @Date
    where 
        RN_D = 1 
        or (RN = 1 and D = @Date) 
        or (RN_Old = 1 and D < @Date)
)
,MyCTE3 as (
    select CustName, Country, RecordedTime
        -- unmarke the bellow comment in order to get the accessories columns I used
        -- This is recommended to understand the line-of-thinking
        --, D, c, RN_D, RN, CurrNo, Cnt, CntToday, RN_Old
        , History = CASE
            WHEN CurrNo = 1 and Cnt = 1 then 'NEW'
            WHEN RN_D = 1 then 'CURRENT'
            else ISNULL(History,'BEFORE')
        END
    from MyCTE2
)
select CustName, Country, RecordedTime--, D, c, RN_D, RN, CurrNo, Cnt, CntToday, RN_Old
    ,Audit = CASE when History='New' then 'ADD' else 'CHANGE'  END
    , History
from MyCTE3

Untuk mempermudah pengujian, saya memasukkan seluruh kueri ke dalam fungsi tabel

DROP FUNCTION IF EXISTS dbo.F
GO
CREATE FUNCTION dbo.F(@Date DATE)
RETURNS TABLE AS RETURN (

--DECLARE @Date DATE = '2018-06-12';
with MyCTE as (
    SELECT 
        t.CustName,t.Country,t.RecordedTime,t.CurrNo, D = CONVERT(DATE, RecordedTime)
        ,RN_D = ROW_NUMBER() 
            OVER (partition by t.CustName order by t.CurrNo desc)
        ,RN = ROW_NUMBER() 
            OVER (partition by t.CustName order by t.CurrNo)
        ,RN_Old = ROW_NUMBER() 
            OVER (partition by t.CustName, (CASE WHEN CONVERT(DATE, RecordedTime) < @Date then 0 else 1 END) order by t.CurrNo desc)
        ,Cnt = COUNT(*) 
            OVER (partition by t.CustName)
        ,CntToday = COUNT(CASE WHEN CONVERT(DATE, RecordedTime) = @Date THEN 1 ELSE NULL END) 
            OVER (partition by t.CustName)
    FROM Test t
    where 
        -- returns rows untill current date
        CONVERT (DATE, RecordedTime) <= @Date 
        -- only if relevnat to current date
        and EXISTS (
            SELECT * FROM test t0 
            where CONVERT (DATE, RecordedTime) = @Date and t0.CustName = t.CustName
        )
)
,MyCTE2 as (
    select
        CustName, Country, RecordedTime, D, CurrNo, RN_D, RN, Cnt, t2.c, History, CntToday, RN_Old
    from MyCTE t1
    left JOIN (select * from (values(1, 'NEW'),(1, 'BEFORE')) t2(c, History) ) t2 
        on t1.CurrNo = t2.c
            and CntToday > 1
            and D = @Date
    where 
        RN_D = 1 
        or (RN = 1 and D = @Date) 
        or (RN_Old = 1 and D < @Date)
)
,MyCTE3 as (
    select CustName, Country, RecordedTime
        -- unmarke the bellow comment in order to get the accessories columns I used
        -- This is recommended to understand the line-of-thinking
        --, D, c, RN_D, RN, CurrNo, Cnt, CntToday, RN_Old
        , History = CASE
            WHEN CurrNo = 1 and Cnt = 1 then 'NEW'
            WHEN RN_D = 1 then 'CURRENT'
            else ISNULL(History,'BEFORE')
        END
    from MyCTE2
)
select CustName, Country, RecordedTime--, D, c, RN_D, RN, CurrNo, Cnt, CntToday, RN_Old
    ,Audit = CASE when History='New' then 'ADD' else 'CHANGE'  END
    , History
from MyCTE3
--order by CustName, RecordedTime
)
GO

Menggunakan fungsi lebih mudah untuk membuat beberapa tes, tetapi mungkin dalam produksi Anda ingin menggunakan kueri langsung

-- Test
select * from F('2018-06-01') order by CustName , RecordedTime
select * from F('2018-06-02') order by CustName , RecordedTime
select * from F('2018-06-03') order by CustName , RecordedTime
select * from F('2018-06-10') order by CustName , RecordedTime
select * from F('2018-06-11') order by CustName , RecordedTime
select * from F('2018-06-12') order by CustName , RecordedTime
select * from F('2018-06-13') order by CustName , RecordedTime
select * from F('2018-06-14') order by CustName , RecordedTime

/**************** Pembaruan pada 19-08 2018 14:05 Waktu Israel ****************/

Saya perhatikan bahwa beberapa informasi lebih penting untuk ditambahkan demi partisipasi dalam utas. Semoga bermanfaat

Pertama, mari kita bandingkan persentase penggunaan sumber daya menurut Rencana Eksekusi dari tiga pertanyaan:(1) Solusi saya, (2) solusi maulik kansara detik setelah memperbarui solusi pertama, dan (3) solusi maulik kansara pertama

Sekarang mari kita periksa gambar EP solusi detik maulik kansara:

Kueri ini memindai tabel 11 kali!



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dapatkan salah satu entri dalam catatan duplikat

  2. Contoh Konversi 'tanggal' ke 'datetime2' di SQL Server (T-SQL)

  3. Bagaimana cara membuat daftar yang dipisahkan koma menggunakan kueri SQL?

  4. Cara Menggunakan FILEPROPERTY() di SQL Server

  5. Bagaimana cara membuat kueri passthrough dalam akses menggunakan koneksi tanpa DSN?