简体   繁体   中英

How do I select 100 records from one table for each unique record from another

I have one table of addresses, another table of coupons. I want to select 10 coupons per address. How would I go about doing that? I know this is very basic, but I've been out of SQL for some time now and trying to get reacquainted with it the best I can...

Table 1

Name      Address
-------------------
Store 1   Address 1
Store 2   Address 2

Table 2

Coupons
--------
coupon1
coupon2
...
coupon19
coupon20

You can use window functions:

select t1.*, t2.coupons
from (
    select t1.*, row_number() over(order by id) rn
    from table1 t1
) t1
inner join (
    select t2.*, row_number() over(order by id) rn
    from table2 t2
) t2 on (t2.rn - 1) / 10 = t1.rn

The idea is to enumerate rows of each table with row_number() , then join the results with a condition on the row numbers. The above query gives you 10 coupons per address.

To get a stable result, you need a column (or a set of columns) in each table that uniquely identifies each row: I assumed id in both tables.

Do you want 10 coupons per store? 100 coupons per store? Your question response is different than the post. Or maybe you'd like to evenly distribute all available coupons across all the stores? Some of this query is building data to be able to demonstrate the output, but the main thing to focus on is the using of NTILE(10) to break up the Coupons into ten groups that can then have a ROW_NUMBER applied to it that gives you ten coupons per id value that can be joined upon...

WITH random_data AS
(
    SELECT  ROW_NUMBER() OVER (ORDER BY id) AS nums
    FROM    sysobjects
),  store_info AS
(
    SELECT  ROW_NUMBER() OVER (ORDER BY nums) AS join_id,
            'Store' + CONVERT(VARCHAR(10),nums) AS StoreName,
            'Address' + CONVERT(VARCHAR(10),nums) AS StoreAddress
    FROM    random_data
),  more_random_data    AS
(
    SELECT  ROW_NUMBER() OVER (ORDER BY t2.nums) AS nums
    FROM    random_data t1
    CROSS   JOIN random_data t2
),  coupons AS
(
    SELECT  NTILE(10) OVER (ORDER BY nums) AS group_id,
            'Coupon' + CONVERT(VARCHAR(10),nums) AS Coupon,
            nums
    FROM    more_random_data
),  coupons_with_join_id AS
(
    SELECT  ROW_NUMBER() OVER (PARTITION BY group_id ORDER BY nums) AS join_id,
            Coupon
    FROM    coupons
)
SELECT  StoreName, StoreAddress, Coupon
FROM    store_info AS si
JOIN    coupons_with_join_id AS cwji
    ON  si.join_id = cwji.join_id
ORDER   BY si.join_id, Coupon

The inherent issue here is that the 2 tables have no relation to each other. So your options are either to force a pseudo relation, like the other answers show, or create a relation between the two tables, like adding a store_name column to the coupon table.

This distributes all coupons (almost) evenly across all adresses:

with addr as
 ( -- prepare addresses by adding a sequence
   select Name, Address, 
      -- 1-n
      row_number() over (order by name) as rn
   from table1
 )
 ,coup as
 ( -- prepare coupons by adding same "sequence"
   select coupons,
      -- 1-n, same number of coupons (+/-1) for each address
      ntile((select count(*) from table1))
      over (order by coupons) as num
   from table2
 )
select * 
from addr 
join coup
on addr.rn = coup.num

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