How to combine/join two results tables by the grouped by column? - sql-server

How can the two individual tables be combined into one results table?
The first query gives the results table
| company_id| Number products sold (2022) |
|-----------|-----------------------------|
| 1 | 151513 |
| ... | ... |
| 958 | 11156 |
SELECT company_id, COUNT(product_id) AS 'Number products sold (2022)'
FROM Sales
WHERE sales_year = 2022
GROUP BY company_id;
And the second query gives the results table
| company_id| Number products sold (2021) |
|-----------|-----------------------------|
| 1 | 81513 |
| ... | ... |
| 958 | 10167 |
SELECT company_id, COUNT(product_id) AS 'Number products sold (2021)'
FROM Sales
WHERE sales_year = 2021
GROUP BY company_id;
However, both tables should be combined to the following table
| company_id| Number products sold (2022) | Number products sold (2021) |
|-----------|-----------------------------|-----------------------------|
| 1 | 151513 | 81513 |
| ... | ... | ... |
| 958 | 11156 | 10167 |

use join in subquery to put them in front of each other
company_id
Number_products_sold_(2022)
Number_products_sold_(2021)
Ids
Values(2022)
Values(2021)
select a.company_id,'Number products sold (2022)','Number products sold (2021)' from
(SELECT company_id, COUNT(product_id) AS 'Number products sold (2022)'
FROM Sales
WHERE sales_year = 2022
GROUP BY company_id) a
join
(SELECT company_id, COUNT(product_id) AS 'Number products sold (2021)'
FROM Sales
WHERE sales_year = 2021
GROUP BY company_id) b
on a.company_id=b.company_id
if you want to put sales_year = 2022 followed by sales_year = 2021 use union
company_id
Number_products_sold
Ids
Values(2022)
Ids
Values(2021)
SELECT company_id, COUNT(product_id) AS 'Number products sold (2022)'
FROM Sales
WHERE sales_year = 2022
GROUP BY company_id;
union all
SELECT company_id, COUNT(product_id) AS 'Number products sold (2021)'
FROM Sales
WHERE sales_year = 2021
GROUP BY company_id;

Related

I'm getting a rollup of the same value twice

I have table sellers where I list every single one of my sellers, and I added the column objective recently.
id |name | team_leader_id | team_leader | objective
--------------------------------------------------
1 |John | 50 | Mark | 30
2 |Jane | 66 | Ryu | 30
3 |Angela | 66 | Ryu | 45
4 |Arthur | 190 | Carol | 35
5 |Anthony| 20 | Adam | 50
I have another table sales where I link my sellers table on seller_id.
sale_id |seller_id |seller_name |item
-------------------------------------
56879 |2 |Jane |4P
23512 |2 |Jane |3P
54827 |2 |Jane |3P
12345 |5 |Anthony |4P
55435 |4 |Arthur |GSM
The query I'm trying is:
SELECT coalesce(seller.team_leader,'') team_leader,
coalesce(sales.seller_name,'TOTAL') seller_name,
seller.objective,
count(*) as quantity
FROM sales
JOIN seller ON seller.id = sales.seller_id
WHERE seller.team_leader_id = 66
GROUP BY seller.team_leader, ROLLUP(sales.seller_name), seller.objective
I noticed that the result I'm getting a duplicate of every line that now has an objective.
I think the problem is because my objective column is new, and I'm joining my sales table with my seller table, it counts the records I had before creating the objective column separately.
So, my expected result would be
team_leader | seller_name | objective | quantity
------------------------------------------------
Ryu | TOTAL | | 3
| Jane | 30 | 3
| Angela | 45 | 0
But this is what I'm getting
team_leader | seller_name | objective | quantity
------------------------------------------------
Ryu | TOTAL | | 1
Ryu | TOTAL | 30 | 2
| Jane | | 1
| Jane | 30 | 2
| Angela | 45 | 0
When the objective appears blank with Jane, it is a sale that she did before I added the objective column.
You can try the following :
SELECT case when seller.name is null then max(seller.team_leader) else '' end as team_leader,
isnull(seller.name,'TOTAL') seller_name,
case when seller.name is null then '' else sum(seller.objective) end objective,
count(sales.seller_id) as quantity
FROM seller
LEFT JOIN sales ON seller.id = sales.seller_id
WHERE seller.team_leader_id = 66
group by ROLLUP(seller.name)
order by team_leader desc, quantity desc
OR if you are okay with not using ROLLUP, you can get the exact same result using the following query.
;with cte as (
SELECT max(team_leader) team_leader,
max(name) seller_name,
max(objective) objective,
count(seller_id) as quantity
FROM seller
LEFT JOIN sales ON seller.id = sales.seller_id
WHERE seller.team_leader_id = 66
GROUP BY seller.id
)
SELECT team_leader, 'TOTAL' seller_name, '' objective, sum(quantity) quantity
FROM cte
GROUP BY team_leader
UNION ALL
SELECT '', seller_name, objective, quantity
FROM cte

TSQL - Group by and sum not grouped column

I'm facing some kind of problem. I have table "Prices" with columns - ProductId, ShopId, Date, Price.
Table contains history of prices for products in diffrent shops. Each product can be in diffrent shop with diffrent price and Date.
I want to get sum of the lastest prices in all shops for each product.
| ProductId | ShopId | Date | Price |
|:---------:|:------:|:----------:|:------:|
| 1 | 1 | 2020.11.10 | 100 |
| 1 | 2 | 2020.11.10 | 120 |
| 2 | 3 | 2020.11.10 | 200 |
| 3 | 3 | 2020.10.05 | 170 |
| 4 | 4 | 2020.11.10 | 200 |
| 4 | 4 | 2019.09.05 | 250 |
The output I want to get is (ShopId and Date can be included in output):
| ProductId | PriceSum |
|:---------:|:--------:|
| 1 | 220 |
| 2 | 200 |
| 3 | 170 |
| 4 | 200 |
I have following query:
SELECT ProductId, ShopId, MAX(Date) as MaxDate
FROM Prices
GROUP BY ShopId, ProductId
ORDER BY ProductId
I've found solution, not the fastest but working.
select st.ProductId, SUM(st.Price)
from Prices as p1
cross apply
(
select ProductId, ShopId, MAX(Date) as MaxDate
from Prices
group by ShopId, ProductId
) as p2
where p2.MaxDate = p1.Dt
and p2.Shopid = p1.ShopId
and p2.ProductId = p1.ProductId
group by p1.ProductId
order by p1.ProductId
In your case DENSE RANK window function can help you. If two or more rows have the same rank value in the same partition, each of those rows will receive the same rank.
WITH LatestPricesCTE AS
(
SELECT *, DENSE_RANK() OVER (PARTITION BY ProductID ORDER BY Date DESC) Rank
FROM Prices
)
SELECT ProductId, SUM(Price) PriceSum
FROM LatestPricesCTE
WHERE Rank = 1
GROUP BY ProductId
For more information:
https://learn.microsoft.com/en-us/sql/t-sql/functions/dense-rank-transact-sql?view=sql-server-ver15
Use window function to identity the latest dates and filter out older recs
;With dat
As (SELECT ProductId, ShopId, Date , Price
, row_number() over partition by prodictid, date order by date desc)r
FROM Prices)
Select Productid
, sum(price) Pricesum
From dat
Where rid=1
Group by productid;

Get all categories with number of associated records with where clause

So I have two tables:
Categories
-------------------
| Id | Name |
-------------------
| 1 | Category1 |
-------------------
| 2 | Category2 |
-------------------
| 3 | Category3 |
-------------------
Products
--------------------------------------------
| Id | CategoryId | Name | CreatedDate |
--------------------------------------------
| 1 | 1 | Product1 | 2017-05-05 |
--------------------------------------------
| 1 | 1 | Product2 | 2017-05-06 |
--------------------------------------------
| 2 | 2 | Product3 | 2017-12-21 |
--------------------------------------------
I need a query to select all categories along with the number of products for each for a specific time range in which those products were created (CreatedDate).
What I currently have is this:
SELECT c.[Name], COUNT(p.[Id]) AS ProductCount
FROM Categories AS c
LEFT JOIN Products AS p ON p.[CategoryId] = c.[Id]
WHERE p.[CreatedDate] BETWEEN '2017-05-01' AND '2017-06-01'
GROUP BY c.[Name]
My issue is that I'm not seeing Category2 and Category3 in the results set because they don't pass the WHERE clause. I want to see all categories in the results set.
Put the where condition in the left join clause
SELECT c.[Name], COUNT(p.[Id]) AS ProductCount
FROM Categories AS c
LEFT JOIN Products AS p ON p.[CategoryId] = c.[Id]
AND p.[CreatedDate] BETWEEN '2017-05-01' AND '2017-06-01'
GROUP BY c.[Name]
This way it is applied to the join only and not to the complete result set.

Finding Location of Duplicate Column [duplicate]

I have a table
+--------+--------+--------+--------+--------+
| Market | Sales1 | Sales2 | Sales3 | Sales4 |
+--------+--------+--------+--------+--------+
| 68 | 1 | 2 | 3 | 4 |
| 630 | 5 | 3 | 7 | 8 |
| 190 | 9 | 10 | 11 | 12 |
+--------+--------+--------+--------+--------+
I want to find duplicates between all the above sales fields. In above example markets 68 and 630 have a duplicate Sales value that is 3.
My problem is displaying the Market having duplicate sales.
This problem would be incredibly simple to solve if you normalised your table.
Then you would just have the columns Market | Sales, or if the 1, 2, 3, 4 are important you could have Market | Quarter | Sales (or some other relevant column name).
Given that your table isn't in this format, you could use a CTE to make it so and then select from it, e.g.
WITH cte AS (
SELECT Market, Sales1 AS Sales FROM MarketSales
UNION ALL
SELECT Market, Sales2 FROM MarketSales
UNION ALL
SELECT Market, Sales3 FROM MarketSales
UNION ALL
SELECT Market, Sales2 FROM MarketSales
)
SELECT a.Market
,b.Market
FROM cte a
INNER JOIN cte b ON b.Market > a.Market
WHERE a.Sales = b.Sales
You can easily do this without the CTE, you just need a big where clause comparing all the combinations of Sales columns.
Supposing the data size is not so big,
make a new temporay table joinning all data:
Sales
Market
then select grouping by Sales and after take the ones bigger than 1:
select Max(Sales), Count(*) as Qty
from #temporary
group by Sales

Finding duplicate in SQL Server Table

I have a table
+--------+--------+--------+--------+--------+
| Market | Sales1 | Sales2 | Sales3 | Sales4 |
+--------+--------+--------+--------+--------+
| 68 | 1 | 2 | 3 | 4 |
| 630 | 5 | 3 | 7 | 8 |
| 190 | 9 | 10 | 11 | 12 |
+--------+--------+--------+--------+--------+
I want to find duplicates between all the above sales fields. In above example markets 68 and 630 have a duplicate Sales value that is 3.
My problem is displaying the Market having duplicate sales.
This problem would be incredibly simple to solve if you normalised your table.
Then you would just have the columns Market | Sales, or if the 1, 2, 3, 4 are important you could have Market | Quarter | Sales (or some other relevant column name).
Given that your table isn't in this format, you could use a CTE to make it so and then select from it, e.g.
WITH cte AS (
SELECT Market, Sales1 AS Sales FROM MarketSales
UNION ALL
SELECT Market, Sales2 FROM MarketSales
UNION ALL
SELECT Market, Sales3 FROM MarketSales
UNION ALL
SELECT Market, Sales2 FROM MarketSales
)
SELECT a.Market
,b.Market
FROM cte a
INNER JOIN cte b ON b.Market > a.Market
WHERE a.Sales = b.Sales
You can easily do this without the CTE, you just need a big where clause comparing all the combinations of Sales columns.
Supposing the data size is not so big,
make a new temporay table joinning all data:
Sales
Market
then select grouping by Sales and after take the ones bigger than 1:
select Max(Sales), Count(*) as Qty
from #temporary
group by Sales

Resources