একটি ব্যাপ্তিতে প্রতি তারিখের জন্য একটি কলাম ফেরত দিন


15

ধরা যাক আমার টেবিল এ: বুকিংসপর্সন

Person_Id    ArrivalDate    DepartureDate
123456       2012-01-01     2012-01-04
213415       2012-01-02     2012-01-07

আমার একটি দৃষ্টিভঙ্গি সহ যা অর্জন করতে হবে তা হ'ল:

Person_Id    ArrivalDate    DepartureDate    Jan-01    Jan-02    Jan-03    Jan-04    Jan-05    Jan-06    Jan-07
123456       2012-01-01     2012-01-04       1         1         1         1
213415       2012-01-02     2012-01-07                 1         1         1         1         1         1

সিস্টেম ইভেন্টগুলির জন্য, সুতরাং প্রতিটি হোটেল বুকিং 1 থেকে 15 দিনের মধ্যে কিছু নিতে পারে তবে এর চেয়ে বেশি কিছু না। যে কোনও ধারণা খুব প্রশংসা হবে।

উত্তর:


27

আপনি PIVOTএই কোয়েরিটি সম্পাদন করতে ফাংশনটি ব্যবহার করতে পারেন । আমার উত্তরে একটি স্ট্যাটিক এবং গতিশীল সংস্করণ উভয়ই অন্তর্ভুক্ত থাকবে কারণ কখনও কখনও স্ট্যাটিক সংস্করণ ব্যবহার করে এটি বোঝা সহজ হয়।

একটি স্ট্যাটিক পিভট হ'ল আপনি যখন কলামগুলিতে রূপান্তর করতে চান এমন সমস্ত মানকে হার্ড-কোড করেন।

-- first into into a #temp table the list of dates that you want to turn to columns
;with cte (datelist, maxdate) as
(
    select min(arrivaldate) datelist, max(departuredate) maxdate
    from BookingsPerPerson
    union all
    select dateadd(dd, 1, datelist), maxdate
    from cte
    where datelist < maxdate
) 
select c.datelist
into #tempDates
from cte c

select *
from
(
    select b.person_id, b.arrivaldate, b.departuredate,
        d.datelist,
        convert(CHAR(10), datelist, 120) PivotDate
    from #tempDates d
    left join BookingsPerPerson b
        on d.datelist between b.arrivaldate and b.departuredate
) x
pivot
(
    count(datelist)
    for PivotDate in ([2012-01-01], [2012-01-02], [2012-01-03],
              [2012-01-04], [2012-01-05], [2012-01-06] , [2012-01-07])
) p;

ফলাফল ( ডেমো সহ এসকিউএল ফিডল দেখুন ):

PERSON_ID | ARRIVALDATE | DEPARTUREDATE | 2012-01-01 | 2012-01-02 | 2012-01-03 | 2012-01-04 | 2012-01-05 | 2012-01-06 | 2012-01-07
=====================================================================================================================================
123456    | 2012-01-01  | 2012-01-04    | 1          | 1          | 1          | 1          | 0          | 0          | 0
213415    | 2012-01-02  | 2012-01-07    | 0          | 1          | 1          | 1          | 1          | 1          | 1

গতিশীল সংস্করণ কলামগুলিতে রূপান্তর করতে মানগুলির তালিকা তৈরি করবে:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

;with cte (datelist, maxdate) as
(
    select min(arrivaldate) datelist, max(departuredate) maxdate
    from BookingsPerPerson
    union all
    select dateadd(dd, 1, datelist), maxdate
    from cte
    where datelist < maxdate
) 
select c.datelist
into #tempDates
from cte c


select @cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(CHAR(10), datelist, 120)) 
                    from #tempDates
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT person_id, arrivaldate, departuredate, ' + @cols + ' from 
             (
                select b.person_id, b.arrivaldate, b.departuredate,
                    d.datelist,
                    convert(CHAR(10), datelist, 120) PivotDate
                from #tempDates d
                left join BookingsPerPerson b
                    on d.datelist between b.arrivaldate and b.departuredate
            ) x
            pivot 
            (
                count(datelist)
                for PivotDate in (' + @cols + ')
            ) p '

execute(@query)

ফলাফলগুলি একই ( ডেমো সহ এসকিউএল ফিডাল দেখুন ):

PERSON_ID | ARRIVALDATE | DEPARTUREDATE | 2012-01-01 | 2012-01-02 | 2012-01-03 | 2012-01-04 | 2012-01-05 | 2012-01-06 | 2012-01-07
=====================================================================================================================================
123456    | 2012-01-01  | 2012-01-04    | 1          | 1          | 1          | 1          | 0          | 0          | 0
213415    | 2012-01-02  | 2012-01-07    | 0          | 1          | 1          | 1          | 1          | 1          | 1

8

আমি পুরানো স্কুল, এবং CASEআমার থেকে কাজ করা আরও সহজ খুঁজে PIVOT। আমি নিশ্চিত যে নীলফিট শীঘ্রই প্রদর্শিত হবে এবং আমাকে লজ্জা দেবে, তবে এর মধ্যে আপনি এই গতিশীল এসকিউএল কোয়েরি নিয়ে খেলতে পারবেন। আপনার টেবিল স্টোরগুলি ধরেই নেওয়া DATEএবং না DATETIME(বা আরও খারাপ VARCHAR):

USE tempdb;
GO

CREATE TABLE dbo.a
(
   Person_Id INT, 
   ArrivalDate DATE, 
   DepartureDate DATE
);

INSERT dbo.a SELECT 123456, '2012-01-01', '2012-01-04'
UNION ALL    SELECT 213415, '2012-01-02', '2012-01-07';

DECLARE @sql NVARCHAR(MAX) = N'SELECT Person_Id';

;WITH dr AS
(
  SELECT MinDate = MIN(ArrivalDate),
         MaxDate = MAX(DepartureDate)
  FROM dbo.a
),
n AS
(
  SELECT TOP (DATEDIFF(DAY, (SELECT MinDate FROM dr), (SELECT MaxDate FROM dr)) + 1)
   d = DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY [object_id])-1, 
     (SELECT MinDate FROM dr))
 FROM sys.all_objects
)
SELECT @sql += ',
  ' + QUOTENAME(d) + ' = CASE WHEN ''' + CONVERT(CHAR(10), d, 120) 
  + ''' BETWEEN ArrivalDate AND DepartureDate THEN ''1'' ELSE '''' END' FROM n;

SELECT @sql += ' FROM dbo.a;'

EXEC sp_executesql @sql;
GO

DROP TABLE dbo.a;

খুব কম কয়েকটি ক্ষেত্রে একটি, বিটিডাব্লু, যেখানে আমি BETWEENতারিখের সীমা অনুসন্ধানের জন্য ন্যায্যতা প্রমাণ করতে পারি ।


0

তারিখগুলির একটি তালিকা উত্পন্ন করার জন্য এটি কীভাবে

declare @Date01 as smalldatetime
declare @Date02 as smalldatetime
select @Date01 = min(periodstart), @Date02 = max(periodend)
    from BookingTable

declare @DateDiff as int
select @DateDiff = (select DATEDIFF(DAY, @Date01, @Date02))
;

WITH Tally (N) AS
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    FROM sys.all_columns a CROSS JOIN sys.all_columns b
)
SELECT DATEADD(day, N, @Date01)
FROM Tally
where N <= @DateDiff
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.