Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

SQL Wielokrotne liczenie w tym samym wierszu z dynamiczną kolumną

Ponieważ używasz SQL Server, możesz zaimplementować funkcję PIVOT, a jeśli masz nieznaną liczbę wartości okresu, będziesz musiał użyć dynamicznego SQL:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME('PeriodId'+cast(periodid as varchar(10))) 
                    from Periods
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT resourcecode, ' + @cols + ' , Total
            from 
            (
               select s.resourcecode, 
                 ''PeriodId''+cast(p.periodid as varchar(10)) period,
                count(*) over(partition by s.resourcecode) Total
               from periods p
               left join schedules s
                 on p.periodid = s.periodid
            ) x
            pivot 
            (
                count(period)
                for period in (' + @cols + ')
            ) p 
            where resourcecode is not null
            order by resourcecode'

execute(@query)

Zobacz SQL Fiddle z wersją demonstracyjną . Daje to wynik:

| RESOURCECODE | PERIODID1 | PERIODID2 | PERIODID3 | PERIODID4 | PERIODID5 | PERIODID6 | PERIODID7 | PERIODID8 | TOTAL |
------------------------------------------------------------------------------------------------------------------------
|           AA |         2 |         0 |         3 |         0 |         0 |         0 |         0 |         0 |     5 |
|           BB |         2 |         1 |         1 |         0 |         0 |         0 |         0 |         0 |     4 |
|           CC |         1 |         1 |         1 |         0 |         0 |         0 |         0 |         0 |     3 |

Na podstawie twojego poprzedniego pytania, które było oznaczone MySQL, zakładam, że używasz MySQL jako bazy danych. Jeśli tak, to nie masz funkcji PIVOT, więc będziesz musiał użyć funkcji agregującej z wyrażeniem CASE do przekształcenia wierszy danych w kolumny.

Jeśli wartości Twoich kolumn są znane, możesz na stałe zakodować zapytanie:

select resourcecode,
  sum(case when period = 'PeriodId1' then 1 else 0 end) PeriodId1,
  sum(case when period = 'PeriodId2' then 1 else 0 end) PeriodId2,
  sum(case when period = 'PeriodId3' then 1 else 0 end) PeriodId3,
  sum(case when period = 'PeriodId4' then 1 else 0 end) PeriodId4,
  sum(case when period = 'PeriodId5' then 1 else 0 end) PeriodId5,
  sum(case when period = 'PeriodId6' then 1 else 0 end) PeriodId6,
  sum(case when period = 'PeriodId7' then 1 else 0 end) PeriodId7,
  sum(case when period = 'PeriodId8' then 1 else 0 end) PeriodId8,
  count(*) Total
from
(
  select concat('PeriodId', p.periodid) Period,
    s.resourcecode
  from periods p
  left join schedules s
    on p.periodid = s.periodid
) d
where resourcecode is not null
group by resourcecode;

Zobacz Skrzypce SQL z wersją demonstracyjną . Ale jeśli wartości będą nieznane lub dynamiczne, będziesz musiał użyć przygotowanej instrukcji, aby wygenerować ciąg sql do wykonania:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN period = ''',
      concat('PeriodId', periodid),
      ''' THEN 1 else 0 END) AS `',
      concat('PeriodId', periodid), '`'
    )
  ) INTO @sql
FROM periods;

SET @sql 
  = CONCAT('SELECT resourcecode, ', @sql, ' , count(*) Total
            from
            (
              select concat(''PeriodId'', p.periodid) Period,
                s.resourcecode
              from periods p
              left join schedules s
                on p.periodid = s.periodid
            ) d
            where resourcecode is not null
            group by resourcecode');


PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

Zobacz Skrzypce SQL z wersją demonstracyjną .



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dowiedz się, czy ograniczenie CHECK jest na poziomie kolumny czy na poziomie tabeli w programie SQL Server (przykłady T-SQL)

  2. Jak wyświetlić wiele zapytań i wyników obok siebie w SQL Server Management Studio (SSMS) — samouczek SQL Server / TSQL, część 14

  3. Konwertuj wartość tekstową w SQL Server z UTF8 na ISO 8859-1

  4. Jak skonfigurować pocztę bazy danych w programie SQL Server (SSMS)

  5. java.lang.ClassNotFoundException:com.microsoft.jdbc.sqlserver.SQLServerDriver :Czy ładuję właściwy sterownik?