sql >> Database teknologi >  >> RDS >> Sqlserver

SQL Multiple tæller på samme række med dynamisk kolonne

Da du bruger SQL Server, kan du implementere PIVOT-funktionen, og hvis du har et ukendt antal periodeværdier, skal du bruge dynamisk 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)
 

Se SQL Fiddle with Demo . Dette giver et resultat:

| 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 |

Baseret på dit tidligere spørgsmål, der var tagget med MySQL, antager jeg, at du bruger MySQL som database. Hvis ja, så har du ikke en PIVOT-funktion, så du bliver nødt til at bruge en aggregeret funktion med et CASE-udtryk for at transformere rækkerne af data til kolonner.

Hvis dine kolonneværdier er kendte, kan du hardkode forespørgslen:

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;
 

Se SQL Fiddle with Demo . Men hvis værdierne vil være ukendte eller dynamiske, skal du bruge en forberedt sætning til at generere en sql-streng til at udføre:

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;
 

Se SQL Fiddle with Demo .



  1. Formular i PDO for at opdatere data

  2. Markér ikke-sammenhængende datointervaller

  3. Brug sammensat primærnøgle som fremmednøgle

  4. Hvordan fjerner man en del af strengen i mysql?