简体   繁体   中英

Print out same row multiple times based on calculated value

I have a query that returns something similar to the following:

Zone    | NeededItems
===========================
209     | 5
213     | 1
216     | 1
220     | 2
218     | 1
219     | 4
215     | 1

The query behind it is something like:

SELECT
    r.Zone as Zone, r.Required - COUNT(i.Item) as NeededItems
FROM
    MyItems i
INNER JOIN
    MyRequirements r ON i.Zone = r.Zone
GROUP BY
    r.Zone, r.Required

Where MyItems looks like: (Value of Item doesn't matter)

Zone    | Item
================
209     | a
209     | b
209     | c
216     | a
220     | a
213     | z
218     | x
219     | q
219     | w
219     | e
219     | r
215     | t

And MyRequirements looks like:

Zone    | Required
======================
209     | 8
213     | 2
216     | 2
220     | 3
218     | 2
219     | 5
215     | 2

What I need to be able to do is print out the Zone multiple times based on the value in Needed. The value in Needed is a calculated value which is what is making this difficult (I can't just remove the count!)

So the results I am looking for is simply a list of zones, each appearing the number of times it is needed.

Zone    
====
209
209
209
209
209
213
216
220
220
218
219     
219
219
219
215

Is there any way in SQL that this can be done? Using SQL Server 2012.

Below is one way to do it - using the e1, e2 and e3 queries are not the cleanest way to do it, but it's the only way that I could manage to get it working.

One bit limitation: it only works for up to 1000 items of each (more than enough for mine.) This could be changed by editing WHERE c<9 but be aware this is recursive so best not to have it more than what is needed.

WITH CTE as
(
    SELECT
        r.Zone as Zone, r.Required - COUNT(i.Item) as NeededItems
    FROM
        MyItems i
    INNER JOIN
        MyRequirements r ON i.Zone = r.Zone
    GROUP BY
        r.Zone, r.Required
),
e1(n,c ) AS
(
    SELECT 1, 0
    UNION ALL
    SELECT n, c + 1
        FROM e1
        WHERE c<9
), -- 10
e2(n) AS
(
    SELECT 1 FROM e1 CROSS JOIN e1 AS b -- 100
),
e3(n) AS
(
    SELECT 1 FROM e1 CROSS JOIN e2 -- 1000
), 
Numbers AS
(
    SELECT n = ROW_NUMBER() OVER (ORDER BY n) FROM e3
)

SELECT
    Zone
FROM
    Numbers
INNER JOIN
    CTE on CTE.NeededItems >= n ORDER BY Zone

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM