Как получить даты календаря в качестве заголовка и получить относительные записи из БД - PullRequest
0 голосов
/ 13 января 2019

Может кто-нибудь, пожалуйста, руководство, как добиться этого, как я пытался с pivot, но он не работает

Name    |Date       |Hours
Sam     |09/01/2019 |9
Sam     |10/01/2019 |3
Sam     |10/01/2019 |4
Sam     |11/01/2019 |7
Marcos  |09/01/2019 |1
Marcos  |10/01/2019 |8
Marcos  |10/01/2019 |2
Marcos  |11/01/2019 |6.5
David   |11/01/2019 |2
David   |10/01/2019 |5
David   |09/01/2019 |3

Нужен вывод как Каждая дата соответствующей записи shoukd имеет сумму = 10 часов Ниже приведен набор результатов, отображающий оставшиеся часы для каждой даты человека 12 января нет в БД, так как никаких записей нет, поэтому для каждого показывается 10 часов до конца

Name    |09/01/2019 |10/01/2019 |11/01/2019 |12/01/2019|
Sam     |1          |3          |3          |10        |
Marcos  |9          |0          |1.5        |10        |
David   |7          |5          |7          |10        |

Ответы [ 3 ]

0 голосов
/ 13 января 2019

Я бы предпочел, чтобы автор поста выполнил эту часть: Запросы для создания таблицы и заполнения.

DECLARE @TABLENAME TABLE (Name varchar(50), WorkDate datetime, hours decimal);

/* Create few records in this table */
INSERT INTO @TABLENAME VALUES('Sam','09/01/2019',9);
INSERT INTO @TABLENAME VALUES('Sam','10/01/2019',3);
INSERT INTO @TABLENAME VALUES('Sam','10/01/2019',4);
INSERT INTO @TABLENAME VALUES('Sam','11/01/2019',7);
INSERT INTO @TABLENAME VALUES('Marcos','09/01/2019',1);
INSERT INTO @TABLENAME VALUES('Marcos','10/01/2019',8);
INSERT INTO @TABLENAME VALUES('Marcos','10/01/2019',2);
INSERT INTO @TABLENAME VALUES('Marcos','11/01/2019',6.5);
INSERT INTO @TABLENAME VALUES('David','11/01/2019',2);
INSERT INTO @TABLENAME VALUES('David','10/01/2019',5);
INSERT INTO @TABLENAME VALUES('David','09/01/2019',3);

Для вашего вопроса вам просто нужно сгруппировать по имени, дате и сводному запросу, чтобы транспонировать

SELECT n.name, 
      10 - SUM(n.Hours) Hours, 
      CONVERT(VARCHAR(10), n.WorkDate, 103) AS 'WorkDate'
FROM @TABLENAME n
GROUP BY n.name , CONVERT(VARCHAR(10), n.WorkDate, 103)
ORDER BY n.name

Вы можете использовать PIVOT QUERY , чтобы транспонировать столбцы в строки, чтобы получать даты в виде заголовков.

Результат:

    name    Hours   WorkDate
1   Sam     1       01/09/2019
2   Sam     3       01/10/2019
3   Sam     3       01/11/2019
4   ....

Попробуйте на SQL FIDDLE

0 голосов
/ 14 января 2019

Вы можете попробовать следующий подход. Шаги:

  • Генерация всех возможных дат в пределах диапазона с использованием рекурсии (или календаря таблица)
  • Получить все комбинации между датами, именами и рассчитанными оставшимися часами
  • Данные PIVOT

T-SQL - это статический пример, если вам нужны данные за разные дни, вам нужно сгенерировать динамический оператор:

---------------------------
-- Table
---------------------------
CREATE TABLE #Table (
   [Name] varchar(10),
   [Date] date,
   [Hours] numeric(5, 1)
)
INSERT INTO #Table
   (Name, [Date], Hours)
VALUES
   ('Sam',     '2019-01-09', 9),
   ('Sam',     '2019-01-10', 3),
   ('Sam',     '2019-01-10', 4),
   ('Sam',     '2019-01-11', 7),
   ('Marcos',  '2019-01-09', 1),
   ('Marcos',  '2019-01-10', 8),
   ('Marcos',  '2019-01-11', 2),
   ('Marcos',  '2019-01-11', 6.5),
   ('David',   '2019-01-11', 2),
   ('David',   '2019-01-10', 5),
   ('David',   '2019-01-09', 3)

---------------------------
-- Statement
---------------------------
;WITH dates AS (
    -- Generate all possible dates within range using recursion
    SELECT CONVERT(date, '2019-01-09') AS [Date]
    UNION ALL
    SELECT DATEADD(day, 1, [Date])
    FROM dates
    WHERE [Date] < CONVERT(date, '2019-01-12')
)
SELECT
   -- Non-pivoted and pivoted columns
   [Name],
   [2019-01-09] AS '2019-01-09',
   [2019-01-10] AS '2019-01-10',
   [2019-01-11] AS '2019-01-11',
   [2019-01-12] AS '2019-01-12'
FROM (
   -- SELECT statement that produces the data
   -- 1. Get all generated dates
   -- 2. CROSS APPLY them with all distinct names
   -- 3. JOIN them with calculted hours per day
   SELECT dates.[Date], names.[Name], 10 - ISNULL(hours.[Hours], 0) AS Hours
   FROM dates
   CROSS APPLY (
      SELECT DISTINCT Name
      FROM #Table
   ) names
   LEFT JOIN (
      SELECT [Name], [Date], SUM([Hours]) AS Hours
      FROM #Table
      GROUP BY [Name], [Date]
   ) hours ON (dates.[Date] = hours.[Date]) AND (names.[Name] = hours.[Name])
) p
PIVOT (
   -- Rotate data with PIVOT
   SUM ([Hours])
   FOR [Date] IN ([2019-01-09], [2019-01-10], [2019-01-11], [2019-01-12])
) AS pvt

Выход:

Name    2019-01-09  2019-01-10  2019-01-11  2019-01-12
David   7.0         5.0         8.0         10.0
Marcos  9.0         2.0         1.5         10.0
Sam     1.0         3.0         3.0         10.0
0 голосов
/ 13 января 2019

Используется временная таблица для достижения этой цели. Не уверен, насколько это тебе поможет.

Create table testStack (Name varchar(64), Date date, Hours INT)

insert into testStack
select 'Sam     ', '09/01/2019 ', '9'
union all select 'Sam     ', '10/01/2019 ', '3'
union all select 'Sam     ', '10/01/2019 ', '4'
union all select 'Sam     ', '11/01/2019 ', '7'
union all select 'Marcos  ', '09/01/2019 ', '1'
union all select 'Marcos  ', '10/01/2019 ', '8'
union all select 'Marcos  ', '10/01/2019 ', '2'
union all select 'Marcos  ', '11/01/2019 ', '6'
union all select 'David   ', '11/01/2019 ', '2'
union all select 'David   ', '10/01/2019 ', '5'
union all select 'David   ', '09/01/2019 ', '3'

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

select @cols = STUFF((SELECT ',' + QUOTENAME(DATE) 
                    from testStack
                    group by DATE
                    order by DATE
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')+ ', [' + CONVERT(varchar(10), GETDATE(), 120) + ']'


set @query = 'SELECT NAME,' + @cols + ' into testtemptable from 
             (
                select NAME, DATE, HOURS
                from testStack
            ) sourcetable
            pivot 
            (
                sum(HOURS)
                for DATE in (' + @cols + ')
            ) pivottable '

execute(@query);

select @cols = STUFF((SELECT ', 10 - ISNULL(' + QUOTENAME(DATE) + ', 0) AS ' + QUOTENAME(DATE)
                    from testStack
                    group by DATE
                    order by DATE
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')+ ', ISNULL([' + CONVERT(varchar(10), GETDATE(), 120) + '], 10) [' + CONVERT(varchar(10), GETDATE(), 120) + ']'

set @query = 'SELECT NAME,' + @cols + ' from testtemptable'

execute(@query);

drop table testtemptable
DROP TABLE testStack
...