SQL Сервер: выберите столбец TOP 10 на основе столбца SELECT TOP 100 - PullRequest
0 голосов
/ 06 февраля 2020

У меня есть 3 таблицы A, B, C

  • A имеет столбцы идентификатора и имени
  • B содержит столбцы идентификатора и PIN-кода
  • C имеет столбцы Имя и Сумма

Чтобы получить общую сумму 10 лучших ПИН-кодов, я использую:

SELECT TOP 10 PIN, SUM(Amount) AS PIN_Amount 
FROM A, B, C 
WHERE
    C.Name IN(A.Name) AND (A.ID = B.ID)
GROUP BY PIN
ORDER BY PIN_Amount DESC

Как получить только сумму ТОП-100 из 10 лучших ПИН-кодов?

Вот мои таблицы:

CREATE TABLE [dbo].[A](
    [ID] [int] NOT NULL,
    [Name] [varchar](10) NULL,
 CONSTRAINT [PK_A] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[B](
    [ID] [int] NULL,
    [PIN] [int] NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[C](
    [Name] [varchar](10) NOT NULL,
    [Amount] [int] NULL,
 CONSTRAINT [PK_C] PRIMARY KEY CLUSTERED 
(
    [Name] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

Ответы [ 4 ]

0 голосов
/ 06 февраля 2020

Начиная с SQL Server 2012 и далее, вы можете использовать оператор OFFSET ... FETCH. Подробнее о OFFSET FETCH

Я бы предложил использовать синтаксис ANSI JOIN.

SELECT B.PIN, SUM(C.Amount) AS total_amount
FROM A
INNER JOIN B ON A.ID = B.ID
INNER JOIN C ON A.Name = C.Name 
GROUP BY B.PIN
ORDER BY total_amount
OFFSET 0 ROWS
FETCH 10 ROWS ONLY;

Для более ранних версий SQL Server вы можете использовать предложение TOP.

SELECT TOP 10 B.PIN, SUM(C.Amount) AS total_amount
FROM A
INNER JOIN B ON A.ID = B.ID
INNER JOIN C ON A.Name = C.Name 
GROUP BY B.PIN
ORDER BY total_amount;
0 голосов
/ 06 февраля 2020

Мое репро, которое показывает СУММУ как 100

CREATE TABLE dbo.A ([ID] int IDENTITY (1,1), [Name] varchar(10))
GO
CREATE TABLE dbo.B (ID INT, PIN INT)
GO
CREATE TABLE dbo.C ([Name] varchar(10), [Amount] INT)
GO

-- This inserts 1000 rows into table C 
DECLARE @counter INT = 1
WHILE @counter <= 1000
BEGIN
    INSERT dbo.C ([Name], [Amount]) 
    VALUES ('Test', 1)
    SELECT @counter += 1
END
GO

-- This inserts 1 record in Table A
INSERT dbo.A ([Name])
VALUES ('Test')
GO

-- This inserts 1 row in table B and ensures that the ID valu is
-- the same as table A
INSERT dbo.B (ID, PIN)
SELECT ID, 1234
FROM dbo.A
GO

SELECT TOP(10) PIN, SUM(D.Amount) as PIN_Amount
FROM A
JOIN B on A.ID = B.ID
CROSS APPLY (SELECT TOP (100) Amount FROM C WHERE Name = A.Name ORDER BY Amount DESC) D
GROUP BY PIN
ORDER BY PIN_Amount DESC

Это приводит к выводу:

PIN         PIN_Amount
1234    100

Это, как и ожидалось, полностью верхние 100 значений из C

0 голосов
/ 06 февраля 2020

Это может помочь вам!

SELECT AID, ANAME, BPIN, C2.AMOUNT
(
    SELECT TOP 10 A.ID AID, A.NAME ANAME, B.PIN BPIN
    FROM A INNER JOIN B
    ON A.ID = B.ID
    --ORDER BY YOUR_COLUMN_IN_CASE
) AS A2
LEFT JOIN (
    SELECT NAME,AMOUNT,
    ROW_NUMBER() OVER(ORDER BY Name) AS ROW_ID
    FROM C
    --ORDER BY NAME,YOUR_COLUMN_IN_CASE
) AS C2
ON A2.ANAME = C2.NAME
WHERE C2.ROW_ID < 101;

ORDER BY в обоих подзапросах вы можете изменить в соответствии с вашими TOP10 & TOP100 требованиями!

0 голосов
/ 06 февраля 2020

Вы можете использовать common_table_expression для достижения этого.

;WITH cte_TempTable AS (
  SELECT TOP 10 PIN, SUM(Amount) AS PIN_Amount 
  FROM A
  INNER JOIN B ON  A.ID = B.ID
  INNER JOIN C ON  C.Name = A.Name
  GROUP BY PIN
  ORDER BY PIN_Amount DESC)

SELECT TOP 100 C.Amount 
FROM A
  INNER JOIN B ON  A.ID = B.ID
  INNER JOIN C ON  C.Name = A.Name
INNER JOIN cte_TempTable ON cte_TempTable.PIN =  B.PIN 
ORDER BY C.Amount DESC
...