SQL SELECT TOP <dynamic>基于CATEGORY / PERCENTAGE

时间:2016-03-21 05:54:14

标签: sql-server tsql select sql-server-2014 dynamic-sql

以下是我的示例数据:

enter image description here

在11行中,我需要从CAT-1中选择60%的行,从CAT-2中选择30%,从CAT-3中选择10%。有人可以帮我构建一个SQL吗?目标是SQL 2014 DB。

4 个答案:

答案 0 :(得分:2)

我还没有测试过该查询,但您应该可以使用UNION ALL

  SELECT TOP(60) PERCENT *
  FROM Table1 
  WHERE Category = 'CAT-1'
UNION ALL
  SELECT TOP(30) PERCENT *
  FROM Table1 
  WHERE Category = 'CAT-2'
UNION ALL
  SELECT TOP(10) PERCENT *
  FROM Table1 
  WHERE Category = 'CAT-3'

显然,您必须定义一些ORDER BY条件,否则前60%将是任意结果。

答案 1 :(得分:2)

虽然你可以做到

ObjectOutputStream

我无法为您的数据中的每个组设置DECLARE @N INT = 20 SELECT TOP (@n) PERCENT * FROM BLAH @N任何人?)。

所以这是使用两个CTE的解决方案。它可能远非最佳:)

测试数据

CROSS APPLY

解决方案

这里我在第一个CTE中对每个组进行排名和计数,然后在第二个CTE中设置'百分比括号范围'(这是为了捕获例如前10%的查询,其中只有两行括号将是50%和100%)。

SELECT *
INTO #Test
FROM (VALUES
(1, 'A', 'CAT-1', 60),
(2, 'B', 'CAT-1', 60),
(3, 'C', 'CAT-1', 60),
(4, 'D', 'CAT-1', 60),
(5, 'E', 'CAT-1', 60),
(6, 'F', 'CAT-2', 30),
(7, 'G', 'CAT-2', 30),
(8, 'H', 'CAT-2', 30),
(9, 'I', 'CAT-3', 10),
(10, 'J', 'CAT-3', 10),
(11, 'K', 'CAT-1', 60)
) A (RowID, Customer, Category, Percentage)

答案 2 :(得分:2)

我将此添加为新答案,因为我的第一个答案是完全不同的。用户&#34; Les H&#34;把我带到了这个:

--Credits to @Les H
SELECT *
INTO #Test
FROM (VALUES
(1, 'A', 'CAT-1', 60),
(2, 'B', 'CAT-1', 60),
(3, 'C', 'CAT-1', 60),
(4, 'D', 'CAT-1', 60),
(5, 'E', 'CAT-1', 60),
(6, 'F', 'CAT-2', 30),
(7, 'G', 'CAT-2', 30),
(8, 'H', 'CAT-2', 30),
(9, 'I', 'CAT-3', 10),
(10, 'J', 'CAT-3', 10),
(11, 'K', 'CAT-1', 60)
) A (RowID, Customer, Category, Percentage)


 SELECT Percentages.*
 FROM (SELECT DISTINCT Category,Percentage FROM #Test) AS c
 CROSS APPLY(SELECT TOP (c.Percentage) PERCENT * FROM #Test WHERE #Test.Category=c.Category ORDER BY #Test.RowID) AS Percentages;

 DROP TABLE #Test;

结果:

1   A   CAT-1   60
2   B   CAT-1   60
3   C   CAT-1   60
4   D   CAT-1   60
6   F   CAT-2   30
9   I   CAT-3   10

答案 3 :(得分:0)

这是一种使用动态SQL的方法。首先,我为客户和类别创建单独的表。然后生成SQL命令。看看:

CREATE TABLE #Cat(CatID INT IDENTITY PRIMARY KEY,Category VARCHAR(100),Percentage INT);
INSERT INTO #Cat(Category,Percentage) VALUES('CAT-1',60),('CAT-2',30),('CAT-3',10);

CREATE TABLE #Cust(CustID INT IDENTITY PRIMARY KEY
                  ,Customer VARCHAR(100)
                  ,CatID INT FOREIGN KEY REFERENCES #Cat(CatID));
INSERT INTO #Cust(Customer,CatID) VALUES
 ('A',1),('B',1),('C',1),('D',1),('E',1),('F',2),('G',2),('H',2),('I',3),('J',3),('K',1);

DECLARE @cmd VARCHAR(MAX)=
(
    SELECT STUFF
    (
        (
            SELECT 'UNION ALL SELECT TOP(' +  CAST(c.Percentage AS VARCHAR(10)) + ') PERCENT * FROM #Cust WHERE CatID=' + CAST(c.CatID AS  VARCHAR(10)) + ' '
            FROM #Cat AS c
            FOR XML PATH('')
        ),1,10,''
    )
);


SET @cmd='SELECT tbl.CustID,tbl.Customer,tbl.CatID,c.Category,c.Percentage FROM(' +  @cmd + ') AS tbl INNER JOIN #Cat AS c ON c.CatID=tbl.CatID';

--This is the generated query
SELECT @cmd;

--And this is its execution
EXEC (@cmd);

DROP TABLE #Cust;
DROP TABLE #Cat;

结果:

1   A   1   CAT-1   60
2   B   1   CAT-1   60
3   C   1   CAT-1   60
4   D   1   CAT-1   60
6   F   2   CAT-2   30
9   I   3   CAT-3   10