Oracle SQL: Insert based on found value in a column given condition from another table - sql

I want to merge my order data into one table which is now in two separate tables:
Order ID and customer code in table Orders:
Order_ID Customer
1 C11
2 C76
4 C32
and order detalis in table Details (with columns Order_ID, Hour, Quantity) in which the ordered quantity for the hours that the order is valid is given:
Order_ID Hour Quantity
1 2 10
1 3 20
2 2 5
2 3 5
2 4 5
4 6 20
4 7 25
I want to merge data of these two tables in one table to have only one row per each order by inserting the quantity for the hours that the order is valid in corresponding column, otherwise zero.
Order_ID Cutomer Hour1 Hour2 Hour3 Hour4 Hour5 Hour6 Hour7 ...
1 C11 0 10 20 0 0 0 0
2 C76 0 5 5 5 0 0 0
4 C32 0 0 0 0 0 20 25
I tried (only for quantity of hour 1):
insert into Merged_Order_Table
(Order_ID,Customer,Hour1)
select
Orders.Order_id,Orders.Customer,
case
when 1 in (select Details.Hour from Details,Orders where
Details.Order_ID = Orders.Order_ID)
then Details.Quantity
else 0
end
from
Orders
inner join
Details
on
Details.Order_ID = Orders.Order_ID;
But got quantity in Hour1 even for orders with no quantity in this hour.

I question why you would want to take nicely normalized data and put it into a table with that structure. I can understand a query returning the data like that, but another table?
In any case, your problem is a common problem when using correlated subqueries. The table being correlated is included in the subquery. Ooops. Here is fix for that:
insert into Merged_Order_Table(Order_ID, Customer, Hour1)
select o.Order_id, o.Customer,
(case when 1 in (select d.Hour from Details d where d.Order_ID = o.Order_ID)
then d.Quantity
else 0
end)
from Orders o;
That said, what you really want is conditional aggregation:
insert into Merged_Order_Table(Order_ID, Customer, Hour1)
select o.Order_id, o.Customer,
sum(case when d.Hour = 1 then d.Quantity else 0 end)
from Orders o left join
Details d
on o.Order_ID = d.Order_ID
group by o.Order_id, o.Customer;

You are on a right track!
you just need one more layer:
select order_id, customer, max(quantity) hour1 from
(your query)
group by order_id, customer
Or you can look into how to do PIVOT tables

Related

Merge row values based on other column value

I'm trying to merge the values of two rows based on the value of another row in a different column. Below is my based table
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3
100
1
C
4
100
1
D
5
20
1
Here is the SQL query I used
select customer_id, property_id, bookings_per_customer, cancellations_per_customer
from table
And this is what I want to see. Any ideas the query to get this would be? We use presto SQL
Thanks!
Customer ID
Property ID
Bookings per customer
Cancellations per customer
A
1
0
1
B
2
10
1
C
3 , 4
100
1
D
5
20
1
We can try:
SELECT
customer_id,
ARRAY_JOIN(ARRAY_AGG(property_id), ',') AS properties,
bookings_per_customer,
cancellations_per_customer
FROM yourTable
GROUP BY
customer_id,
bookings_per_customer,
cancellations_per_customer;

How to I stop duplication on SQL join where I have order_ids and when people order more than 1 item (so multiple product_ids) to calculate discounts?

So my problem is my discount number is blowing up because an order has a discount for the entire order, but I am making a dataset where there are multiple lines for each order to represent each product in the order. Instead of the discount only applying once to the order, it adds the discount for every line.
what is happening
order_id
product_id
quantity
amount
discount
1
a
1
5
0
2
a
1
5
7
2
b
1
10
7
3
a
1
5
5
3
b
1
10
5
3
c
1
15
5
what i want
order_id
product_id
quantity
amount
discount
1
a
1
5
0
2
a
1
5
7
2
b
1
10
0
3
a
1
5
5
3
b
1
10
0
3
c
1
15
0
I just want the discount to be applied once per order, and my join is using order_id so that is why the discount is applying multiple times. I would attach my code, but it's a decent sized CTE
Figured it out. I did need to use a row_number() Over Partition by Order id, but I was also losing records if the order had more than 1 item. The solution was to use a CASE WHEN statement.
CASE WHEN ORDER_ROW_COUNT = 1 THEN DISCOUNT ELSE 0 END
this allowed me to keep the records without duplicating the discounts
You’re joining on a field that isn’t unique so the join is returning all the records for that order Id and therefore the discount is being applied to all the records for that order Id. You need some sort of differentiator field. Something that is unique in each orders data set.
Example:
Select *, row_number () over(partition by order_id order by order_id) as rownumber into #temp from table
This should give you something like in the picture.
rownumber table image
Then join on order_Id = order_Id and rownumber =1 and this would only update the first record for each order.

SQL: calculation on two columns with multiple group by statements

I have a table which has the following columns:
user_id - includes duplicates
product_id - includes duplicates
purchases - number of purchases of given product_id
My table looks somewhat like this:
user_id date product_id purchases
0 1 1 1 4
1 1 2 1 0
2 1 3 2 0
3 1 4 2 0
4 2 1 1 1
5 2 2 1 0
6 2 3 1 1
7 3 1 2 0
8 3 2 3 0
9 4 1 5 1
My goal is to calculate the following metric:
% of products that were purchased at least once, grouped by user
For example: user 1 had 2 products, one of them got purchased at least once, the other one did not get purchased at all. So the metric would be the number of products that got purchased at least once / number of all products per user: 1/2 * 100 = 50%
I have little SQL experience so I do not have any legitimate code that could be corrected.
My desired output would be like this:
user_id total_products products_with_purchases metric
0 1 2 1 50%
1 2 1 1 100%
2 3 2 0 0%
3 4 1 1 100%
I would appreciate seeing a good practice solution to this problem. Many thanks!
select
user_id,
count(distinct product_id) as total_products,
count(distinct case when purchases > 0 then product_id end) as products_with_purchases,
100.00 * count(distinct case when purchases > 0 then product_id end)
/ count(distinct product_id) as metric
from T as t
group by user_id
https://rextester.com/EDSY39439
You can do this all in one query but this is the type of situation where it is easier to understand with sub-queries -- sql optimizer should make it fast.
select
user_id,
total_products,
products_with_purchase,
(products_with_purchase / total_products) * 100 as metric
from (
select -- group by user to get totals
user_id,
count(product_id) as total_products,
sum(case when purchases > 0 then 1 else 0 end) as products_with_purchase
from ( -- group by user and product and get purchase items
SELECT user_id, product_id, sum(purchases) as purchases
FROM table
GROUP BY user_id, product_id
) X
group by user_id
) X2
I Am Mohit Sahni
you can solve the above problem with the below SQL Code:
select
user_id,
count(distinct product_id) as total_products,
sum(case when purchases = 0 then 0 else 1 end) as products_with_purchases,
((sum(case when purchases = 0 then 0 else 1 end))/count(distinct product_id))*100 as metric
from
table
group by
user_id

Microsoft SQL - Counting total of matching values in other table

I have a SQL data scructure like this.
Table 1
http://pbrd.co/1x6TAl3
Table 2
http://pbrd.co/1x6TIRw
I'm trying to count the number of times each item_num has been sold based on the item_qty value in the second table.
Each item_num can appear multiple times in the second table.
I need a way to add the total item_qty for each associated item_num and output it to show how many times an item has been sold.
The correct output ordering by total quantity sold in descending order should look like this.
item_num: 4 7 6
qty_sold: 11 5 4
Try this:
SELECT
a.item_num
, SUM(b.item_qty) as "qty_sold"
FROM
Table1 a
LEFT JOIN
Table2 b
ON a.item_num = b.item_num
GROUP BY
a.item_num
ORDER BY
qty_sold DESC
SELECT A.Item_num , A.Item_name , sum(B.Item_Qty) from Table1 as A inner join Table2 as B
on A.Item_num=B.Item_num
group by A.Item_num , A.Item_name
result:
item_num item_name Item_qty
1 A 1
2 B 1
4 D 11
6 F 4
7 G 5

Need a query to find count of a column record?

I have a table like this,
ProductId CategoryID bIsPrimary
1 5 1
1 6 0
1 7 0
2 18 1
2 19 1
I need a output like this,
ProductID PrimaryCategoryCount
1 1
2 2
Basically i need to find the the number of primary categories for each product.
SELECT ProductId, COUNT(*)
FROM SomeTable
WHERE bIsPrimary <> 0
GROUP BY ProductId
SELECT
ProductId
,sum(case when bIsPrimary = 1 then 1 else 0 end) as PrimaryCategoryCount
from
Table
group by
ProductId
or
SELECT
ProductId
,count(CategoryId)
from
Table
where bIsPrimiary = 1
group by ProductId
Both will provide you the same result. Pick up one which suits you more or is faster.
SELECT ProductId, COUNT(bIsPrimary)
FROM yourTable
GROUP BY ProductId
This is how I'd do it. WHERE clause isn't necessary here if I'm not mistaken.