Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

SQL - Трябва да разделя обща стойност на множество редове в друга таблица

Можете да го направите по следния начин, тази заявка първо попълва класни стаи с най-голям капацитет:

DECLARE @School TABLE (School_Id INT,Course_Id 
    VARCHAR(50), Total_Students INT)
DECLARE @Class TABLE (School_Id INT,Course_Id 
    VARCHAR(50), Class_ID VARCHAR(50), Capacity INT)
INSERT @School VALUES 
   (1,         'Acct101'        ,150),
   (1,         'Acct102'        ,100),
   (2,         'Acct101'        ,110),
   (2,         'Acct102'        ,130)
INSERT @Class VALUES 
   (1,         'Acct101'     ,'A1'       ,65),
   (1,         'Acct101'     ,'A2'       ,50),
   (1,         'Acct101'     ,'A3'       ,70),
   (1,         'Acct102'     ,'Ab1'      ,100),
   (1,         'Acct102'     ,'Ab2'      ,100),
   (2,         'Acct101'     ,'B1'       ,80),
   (2,         'Acct101'     ,'B2'       ,90)

;WITH y AS (
SELECT  a.*,
        ROW_NUMBER() OVER 
            (PARTITION BY a.School_ID, a.Course_ID ORDER BY a.Capacity DESC) 
            CapacitiyOrderPerSchoolAndCourse,
        SUM(a.Capacity) OVER 
            (PARTITION BY a.School_ID, a.Course_ID) 
            TotalCapacityForSchoolAndCourse,
        b.Total_Students TotalParticipants
FROM    @Class a
JOIN    @School b ON 
        b.School_Id = a.School_Id
        AND b.Course_Id = a.Course_Id
), z AS(
SELECT  x.School_Id, 
        x.Course_Id, 
        y.TotalCapacityForSchoolAndCourse, 
        y.TotalParticipants,
        CASE WHEN y.TotalParticipants < SUM(x.Capacity) THEN 
                y.TotalParticipants
            ELSE 
                SUM(x.Capacity) 
            END NumberOfStudentsInClasses,
        MIN(y.Capacity) ClassCapacity,
        y.Class_ID ClassName,
        MIN(y.Capacity) - 
        CASE WHEN y.TotalParticipants - SUM(x.Capacity) < 0 THEN 
               ABS(y.TotalParticipants - SUM(x.Capacity))
            ELSE
               0
            END StudentsInClass
FROM    y
JOIN    y x ON x.School_Id = y.School_Id 
        AND x.Course_Id = y.Course_Id 
        AND x.CapacitiyOrderPerSchoolAndCourse 
                <= y.CapacitiyOrderPerSchoolAndCourse
GROUP   BY x.School_Id, 
        x.Course_Id, 
        y.CapacitiyOrderPerSchoolAndCourse, 
        y.Class_ID, 
        y.TotalCapacityForSchoolAndCourse, 
        y.TotalParticipants
)

SELECT  
        z.School_Id, 
        z.Course_Id, 
        z.TotalCapacityForSchoolAndCourse, 
        z.TotalParticipants,
        z.ClassName,
        z.ClassCapacity,
        CASE WHEN StudentsInClass < 0 THEN 
                0 
            ELSE 
                StudentsInClass 
            END StudentsInClass
FROM    z

Ако искате всяка класна стая да има определен брой ученици, можете да го направите по следния начин (той разпределя брой ученици за всяка класна стая според нейния капацитет):

;WITH y AS (
SELECT  a.*,
        SUM(a.Capacity) OVER 
            (PARTITION BY a.School_ID, a.Course_ID) 
            AS TotalCapacityForSchoolAndCourse,
        b.Total_Students TotalParticipants
FROM    @Class a
JOIN    @School b ON 
        b.School_Id = a.School_Id
        AND b.Course_Id = a.Course_Id
), z AS(
SELECT  y.School_Id, 
        y.Course_Id, 
        y.TotalCapacityForSchoolAndCourse, 
        y.TotalParticipants,
        MIN(y.Capacity) ClassCapacity,
        y.Class_ID,
        MIN(y.Capacity) * 1.0 / y.TotalCapacityForSchoolAndCourse 
            AS PercentOfCapacity,
        ROUND(
            MIN(y.Capacity) * 1.0 / y.TotalCapacityForSchoolAndCourse 
                * TotalParticipants
            , 0, 0) 
            AS NumberOfStudents
FROM    y
GROUP   BY y.School_Id, 
        y.Course_Id, 
        y.Class_ID, 
        y.TotalCapacityForSchoolAndCourse, 
        y.TotalParticipants
)
, i AS(
SELECT  
        z.School_Id, 
        z.Course_Id, 
        z.TotalCapacityForSchoolAndCourse, 
        z.TotalParticipants,
        z.Class_ID,
        z.ClassCapacity,
        PercentOfCapacity,
        NumberOfStudents,
        SUM(NumberOfStudents) OVER 
            (PARTITION BY z.School_Id, z.Course_Id) 
            AS SumNumberOfStudents,
        ROW_NUMBER() OVER 
            (PARTITION BY z.School_Id, z.Course_Id 
                ORDER BY NumberOfStudents) 
            AS ClassWithSmallestCapacity
FROM    z
), j AS(
SELECT  i.School_Id, 
        i.Course_Id, 
        i.TotalCapacityForSchoolAndCourse, 
        i.TotalParticipants,
        i.Class_ID,
        i.ClassCapacity,
        i.PercentOfCapacity,
        i.NumberOfStudents,
        i.NumberOfStudents +
        CASE WHEN ClassWithSmallestCapacity = 1 THEN 
                TotalParticipants - SumNumberOfStudents 
            ELSE 0 
            END AS NumberOfStudents2
FROM    i
)

SELECT  *
FROM    j


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Неуспешно актуализиране на база данни .mdf, защото базата данни е само за четене (приложение за Windows)

  2. SQL Server проверява чувствителността към малки и малки букви?

  3. Преименуване на потребителски дефиниран тип данни в SQL Server (T-SQL)

  4. Доставчикът на OLE DB Microsoft.ACE.OLEDB.12.0 за свързан сървър (null) върна съобщение Отметката е невалидна.

  5. Как да намеря всички тригери, свързани с таблица с SQL Server?