请考虑以下代码:
Declare @MyMinMaxTable Table
(
[Min] int,
[Max] int,
[Desc] NVARCHAR(50)
)
Insert into @MyMinMaxTable
values (0,12,N'Child'),
(13,19,N'Teenager'),
(20,25,N'Youth'),
(25,40,N'Middle-aged'),
(40,99,N'Old')
Declare @MyTable Table
(
Id int identity(1,1),
[Year] int,
Age int,
MyCol2 int,
MyCol3 int null
)
Insert into @MyTable
([Year], Age, MyCol2, MyCol3)
values
(2012, 10, 1 , 1),
(2012, 28, 2 , 3),
(2012, 14, 1 , 7),
(2012, 24, 3 , 3),
(2012, 80, 1 , 6),
(2012, 39, 1 , 3),
(2012, 45, 1 , 5),
(2012, 23, 2 , 6),
(2012, 72, 3 , 8),
(2012, 17, 1 , null),
(2012, 62, 4 , 9),
(2012, 20, 1 , null),
(2012, 5, 1 , 9),
(2012, 8, 1 , 9),
(2012, 25, 1 , null),
(2012, 41, 2 , 2),
(2012, 26, 1 , 2),
(2012, 33, 4 , 2),
(2012, 40, 1 , 2),
(2012, 33, 2 , 3),
(2012, 41, 1 , 5),
(2012, 53, 1 , null),
(2012, 37, 1 , 3)
Declare @Result Table
(
C0 NVARCHAR(50),
c1 decimal(5,2),
C2 decimal(5,2),
C3 decimal(5,2)
)
CURSOR部分:
DECLARE @Min int;
DECLARE @Max int;
DECLARE @Desc nvarchar(50);
DECLARE mycur CURSOR
FOR
SELECT [min],
[max],
[Desc]
FROM @MyMinMaxTable
OPEN mycur
FETCH NEXT FROM mycur INTO @Min, @Max, @Desc
WHILE (@@fetch_status = 0)
BEGIN
INSERT INTO @Result
SELECT @Desc As c0,
(Cast(COUNT(CASE when Age >= @Min AND Age <= @Max THEN 1 END) as decimal(5,2)) / cast(COUNT(Id) as decimal(5,2))) As c1,
(Cast(COUNT(CASE when MyCol2 = 1 AND MyCol3 IS NOT NULL THEN 1 END) as decimal(5,2)) / cast(COUNT(CASE when Age >= @Min AND Age <= @Max THEN 1 END) as decimal(5,2))) As c2,
(Cast(COUNT(CASE when Age >= @Min AND Age <= @Max ANd MyCol2 = 1 THEN 1 END) as decimal(5,2)) / cast(COUNT(CASE when MyCol2 = 1 THEN 1 END) as decimal(5,2))) As c3
FROM @MyTable AS td
FETCH NEXT FROM mycur INTO @Min, @Max, @Desc
END
CLOSE mycur
DEALLOCATE mycur
SELECT * FROM @Result
问题是我要删除CURSOR
并在没有它的情况下编写查询。在这种情况下它怎么可能?
答案 0 :(得分:5)
尝试使用CROSS JOIN
并过滤where子句或条件CASE
语句。目前还不清楚你的最终目标是什么,所以下面的总量必须调整,但这可能是一个好的开始:
SELECT
mm.[Desc],
(CAST(SUM(CASE WHEN MyCol1 >= mm.Min AND MyCol1 <= mm.Max THEN 1 ELSE 0 END) AS DECIMAL(5,2)) / CAST(COUNT(Id) AS DECIMAL(5,2))) AS C1,
(CAST(SUM(CASE WHEN MyCol2 = 1 AND MyCol3 IS NOT NULL THEN 1 END) AS DECIMAL(5,2)) / CAST(SUM(CASE WHEN MyCol1 >= mm.Min AND MyCol1 <= mm.Max THEN 1 ELSE 0 END) AS DECIMAL(5,2))) AS C2,
(CAST(SUM(CASE WHEN MyCol1 >= mm.Min AND MyCol1 <= mm.Max AND MyCol2 = 1 THEN 1 ELSE 0 END) AS DECIMAL(5,2)) / CAST(SUM(CASE WHEN MyCol2 = 1 THEN 1 ELSE 0 END) AS DECIMAL(5,2))) AS C3
FROM MyTable td
CROSS JOIN MyMinMaxTable mm
GROUP BY mm.[Desc]
答案 1 :(得分:2)
这是一个解决方案。我解开你的查询并重新编写它。 如果你添加额外的范围,并且不需要CROSS APPLY,硬编码的子查询范围或其他任何东西,这个继续工作。
排序是一项练习: - )
Declare @MyMinMaxTable Table
(
[Min] int,
[Max] int,
[Desc] NVARCHAR(50)
)
Insert into @MyMinMaxTable
values (0,12,N'Child'),
(13,19,N'Teenager'),
(20,25,N'Youth'),
(25,40,N'Middle-aged'),
(40,99,N'Old')
Declare @MyTable Table
(
Id int identity(1,1),
[Year] int,
MyCol1 int,
MyCol2 int,
MyCol3 int null
)
Insert into @MyTable
([Year], MyCol1, MyCol2, MyCol3)
values
(2012, 10, 1 , 1),
(2012, 28, 2 , 3),
(2012, 14, 1 , 7),
(2012, 24, 3 , 3),
(2012, 80, 1 , 6),
(2012, 39, 1 , 3),
(2012, 45, 1 , 5),
(2012, 23, 2 , 6),
(2012, 72, 3 , 8),
(2012, 17, 1 , null),
(2012, 62, 4 , 9),
(2012, 20, 1 , null),
(2012, 5, 1 , 9),
(2012, 8, 1 , 9),
(2012, 25, 1 , null),
(2012, 41, 2 , 2),
(2012, 26, 1 , 2),
(2012, 33, 4 , 2),
(2012, 40, 1 , 2),
(2012, 33, 2 , 3),
(2012, 41, 1 , 5),
(2012, 53, 1 , null),
(2012, 37, 1 , 3)
SELECT
MMT.[Desc]
--Ratio of (Age Bracket Matches) / (ALL Rows)
, CAST(COUNT(1) / (SELECT CAST(COUNT(1) AS DECIMAL(15,2)) AS TotalRows FROM @MyTable) AS DECIMAL(15,2)) AS C1
--Ratio of (Rows WHERE MyCol2 = 1 and MyCol3 = NULL) / (Age Bracket Matches)
, CAST((SELECT COUNT(1) FROM @MyTable WHERE MyCol2 = 1 AND MyCol3 IS NOT NULL) / CAST(COUNT(1) AS DECIMAL(15,2)) AS DECIMAL(15,2)) AS C2
--Ratio of (Age Bracket Matches WHERE MyCol2 = 1) / (Rows WHERE WHERE MyCol2 = 1)
, CAST(SUM(CASE WHEN T.MyCol2 = 1 THEN 1 ELSE 0 END) / (SELECT CAST(COUNT(1) AS DECIMAL(15,2)) FROM @MyTable WHERE MyCol2 = 1) AS DECIMAL(15,2)) AS C3
FROM
@MyMinMaxTable AS MMT
INNER JOIN @MyTable AS T ON
T.MyCol1 BETWEEN MMT.[Min] AND MMT.[Max]
GROUP BY
MMT.[Desc]
答案 2 :(得分:0)
好像你试图将数据分成几组。试试这个查询。但我不确定第三栏,特别是没有样本数据
{{1}}
答案 3 :(得分:0)
另一种方法可以是使用CROSS APPLY
。
SELECT MM.[Desc],
CAST(C1.C1Count AS DECIMAL(15, 2)) / CAST(Tot.TotCount AS decimal (15, 2)) AS C1,
CAST(C2.C2Count AS DECIMAL(15, 2)) / CAST(C1.C1Count AS decimal (15, 2)) AS C2,
CAST(C3.C3Count AS DECIMAL(15, 2)) / CAST(C4.C4Count AS decimal (15, 2)) AS C2
FROM @MyMinMaxTable MM
CROSS APPLY (SELECT COUNT(MyCol1) AS C1Count
FROM @MyTable
WHERE ( MyCol1 BETWEEN MM.Min AND MM.Max )) C1
CROSS APPLY (SELECT COUNT(*) C2Count
FROM @MyTable
WHERE MyCol2 = 1
AND MyCol3 IS NOT NULL)C2
CROSS APPLY (SELECT COUNT(*) C3Count
FROM @MyTable
WHERE MyCol1 >= mm.Min
AND MyCol1 <= mm.Max
AND MyCol2 = 1)C3
CROSS APPLY (SELECT COUNT(*) C4Count
FROM @MyTable
WHERE MyCol2 = 1)C4
CROSS APPLY (SELECT COUNT(*) TotCount
FROM @MyTable)Tot
以下是上述查询的输出。
Desc C1 C2 C2
---------- -------------------- --------------------- ---------------------
Child 0.130434782608695652 3.666666666666666666 0.200000000000000000
Teenager 0.086956521739130434 5.500000000000000000 0.133333333333333333
Youth 0.173913043478260869 2.750000000000000000 0.133333333333333333
Middle-aged 0.347826086956521739 1.375000000000000000 0.333333333333333333
Old 0.347826086956521739 1.375000000000000000 0.333333333333333333
答案 4 :(得分:0)
我认为在这种情况下可以预先计算&#34;计算@ MyTable&#34;中的所有记录,“@ MyTol2中的记录计数,其中MyCol2 = 1且MyCol3不为空”和“计数@MyTable中的记录,其中MyCol2 = 1“并将它们存储到变量中。
这将使脚本更易读,更容易理解。
在这里。希望这会有所帮助。
Declare @MyMinMaxTable Table
(
[Min] int,
[Max] int,
[Desc] NVARCHAR(50)
)
Insert into @MyMinMaxTable
values (0,12,N'Child'),
(13,19,N'Teenager'),
(20,25,N'Youth'),
(25,40,N'Middle-aged'),
(40,99,N'Old')
Declare @MyTable Table
(
Id int identity(1,1),
[Year] int,
Age int,
MyCol2 int,
MyCol3 int null
)
Insert into @MyTable
([Year], Age, MyCol2, MyCol3)
values
(2012, 10, 1 , 1),
(2012, 28, 2 , 3),
(2012, 14, 1 , 7),
(2012, 24, 3 , 3),
(2012, 80, 1 , 6),
(2012, 39, 1 , 3),
(2012, 45, 1 , 5),
(2012, 23, 2 , 6),
(2012, 72, 3 , 8),
(2012, 17, 1 , null),
(2012, 62, 4 , 9),
(2012, 20, 1 , null),
(2012, 5, 1 , 9),
(2012, 8, 1 , 9),
(2012, 25, 1 , null),
(2012, 41, 2 , 2),
(2012, 26, 1 , 2),
(2012, 33, 4 , 2),
(2012, 40, 1 , 2),
(2012, 33, 2 , 3),
(2012, 41, 1 , 5),
(2012, 53, 1 , null),
(2012, 37, 1 , 3)
Declare @Result Table
(
C0 NVARCHAR(50),
c1 decimal(5,2),
C2 decimal(5,2),
C3 decimal(5,2)
)
-- ANSWER BEGIN HERE
-- The count all record in @MyTable
DECLARE @CountAll DECIMAL(5,2)
SET @CountAll = (SELECT COUNT(1) FROM @MyTable)
-- The count record in @MyTable where MyCol2 = 1 and MyCol3 is not null
DECLARE @CountMyCol2Eq1AndMyCol3NotNull DECIMAL(5,2)
SET @CountMyCol2Eq1AndMyCol3NotNull = (SELECT COUNT(1) FROM @MyTable WHERE MyCol2 = 1 AND MyCol3 IS NOT NULL)
-- The count record in @MyTable where MyCol2 = 1
DECLARE @CountMyCol2Eq1 DECIMAL(5,2)
SET @CountMyCol2Eq1 = (SELECT COUNT(1) FROM @MyTable WHERE MyCol2 = 1)
INSERT INTO @Result
SELECT mm.[Desc],
COUNT(1) / @CountAll,
@CountMyCol2Eq1AndMyCol3NotNull / COUNT(1),
SUM(CASE WHEN tt.MyCol2 = 1 THEN 1 ELSE 0 END) / @CountMyCol2Eq1
FROM @MyMinMAxTable mm
JOIN @MyTable tt
ON mm.[Min] <= tt.Age
AND mm.[Max] >= tt.Age
GROUP BY mm.[Desc]
SELECT * FROM @Result