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.