简体   繁体   中英

SQL Server: query multiple tables to create a pre-formated “template” csv for export into Excel

I am trying to create the SQL necessary to accomplish the following. As an aside, I am using server side Report Builder against a hosted SQL Server database so am limited in what I can do. There are 3 tables. A salesperson table (sales), an items table (items), and a transaction table (tx).

Here is an example:

Sales Person table (sales)

Person A
Person B

Items ID table (items)

  10   
  20
  30
 100
 200
 300
1000
2000
3000

Transaction table (tx)

100 (person A)
300 (person B)
300 (person A)
200 (person B)

Desired result in Report Builder:

Person A
Item 100: 1
Item 200: 0 (NULL)
Item 300: 1

-- NEW PAGE --

Person B:
Item 100: 0 (NULL)
Item 200: 1
Item 300: 1

My problem: here is the SQL I came up with. I need to be able to generate a consistent result set, regardless of whether an item was sold or not by a particular salesperson for easier import into Excel. In addition, I am only looking for items whose code is between 100 and 300 and within a specified date range. My SQL is ignoring the date range and item code range. I originally had these instructions in a WHERE clause but it returned only those lines that were in both tables and I lost the placeholder for any itemcode where the value was null (acting as an INNER join). Within Report Builder I will be counting how many of each items were sold by salesperson.

SELECT  
    tx.date, sales.salesperson, items.itemcode
FROM 
    tx
LEFT OUTER JOIN 
    itemcode ON (tx.itemcode = items.itemcode) 
             AND (date BETWEEN "10/1/2017" AND "12/31/2017") 
             AND (itemcode BETWEEN "100" AND "300")
INNER JOIN 
    sales ON (tx.salesID = sales.salesID)
ORDER BY 
    itemcode ASC

Many thanks for any and all insight into my challenge!

If you want all sales people and all items, then you can generate the rows using a cross join . You can bring in the available data using left join or exists :

select s.person, i.itemcode,
       (case when exists (select 1
                          from tx
                          where tx.salesid = s.salesid and tx.itemcode = i.itemcode
                         )
             then 1 else 0
        end) as has_sold
from sales s cross join
     items i 
where i.itemcode between 100 and 300
order by s.saledid, i.itemcode;

If you want the count of items, use left join and group by :

select s.person, i.itemcode, count(tx.salesid) as num_sold
from sales s cross join
     items i left join
     tx
     on tx.salesid = s.salesid and tx.itemcode = i.itemcode
where i.itemcode between 100 and 300
order by s.saledid, i.itemcode;

Here's an example that uses both cross join (to get all combinations of sales and items) and left join (to get the transactions for given dates)

SELECT  
    tx.date, sales.salesperson, items.itemcode
FROM 
    Items
CROSS JOIN 
    sales
LEFT OUTER JOIN 
     tx ON (items.itemcode = tx.itemcode) 
     AND date BETWEEN '10/1/2017' AND '12/31/2017'
     AND (tx.salesID = sales.salesID)
WHERE
    (items.itemcode BETWEEN '100' AND '300')
ORDER BY 
    itemcode ASC

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