Grouping by multiple fields - sql

I have a table of ParentID's which are products made by combining the required amount of the corresponding BaseID product.
Product table:
ParentID BaseID Required UOH
-------------------------------------
1 55 1 400
1 56 .5 400
2 55 1 400
2 57 1 400
3 58 1 0
I need to select the ParentID's where there are enough of each required base product (UOH) to create the Parent.
The Query should return
ParentID
----------------
1
2
The only way I know how to do this is by using a pivot view. Is there another or a better way to accomplish this?
Thanks

You can use group by and having:
select parentid
from table t
group by parentid
having sum(case when uoh < required then 1 else 0 end) = 0
The having clause counts the number of times where uoh is less than required. If the count is zero, then all base ids have sufficient amounts.

Related

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 transform table with sum based on values

i have table like this:
operation_id
order_id
qty
qty_type
detail_type
1
1
240
ready
glued
1
1
199
ready
unglued
1
1
100
done
glued
1
2
50
ready
glued
and would like to transform into this. it means to add 4 columns and to sum them from above table based on a conditions, like detail_type = 'glued', qty_type = 'ready' etc.
operation_id
order_id
qty_glued_ready
qty_unglued_ready
qty_glued_done
qty_unglued_done
1
1
240
199
10
10
can somebody help me how query should look like?
I assume it is just an example that you have mentioned in your OP and it is not accurate according to your table data you have mentioned.
I don't understand how your qty_glued_done is 10
But here is something you can start working out with:
SELECT o.`operation_id`, o.`order_id`,
SUM(CASE WHEN `detail_type`='glued' AND o.`qty_type`='ready' THEN o.`qty` ELSE 0 END) AS qty_glued_ready,
SUM(CASE WHEN `detail_type`='unglued' AND o.`qty_type`='ready' THEN o.`qty` ELSE 0 END) AS qty_unglued_ready
(and so on)
FROM `operation_table` o GROUP BY o.`operation_id`

Find whether id matches and substitute using Case Hive query

I have a table called "Scan" customer transactions where an individual_id appears once for every different transaction and contains column like scan_id.
I have another table called ids which contains random individual_ids sampled from Scan Table
I would like to join ids with scan and get a single record of ids and scan_id if it matches certain values.
Suppose data is like below
Scan table
Ids scan_id
---- ------
1 100
1 111
1 1000
2 100
2 111
3 124
4 1000
4 111
Ids table
id
1
2
3
4
5
I want below output i.e if scan_id matches either 100 or 1000
Id MT
------ ------
1 1
2 1
3 0
4 1
I executed below query and got error
select MT, d.individual_id
from
(
select
CASE
when scan_id in (90069421,53971306,90068594,136739913,195308160) then 1
ELSE 0
END as MT
from scan cs join ids r
on cs.individual_id = r.individual_id
where
base_div_nbr =1
and
country_code ='US'
and
retail_channel_code=1
and visit_date between '2019-01-01' and '2019-12-31'
) as d
group by individual_id;
I would appreciate any suggestions or help with regard to this Hive query. If there is an efficient way of getting this job done. Let me know.
Use a group by:
select s.individual_id,
max(case when s.scan_id in (100, 1000) then 1 else 0 end) as mt
from scan s
group by s.individual_id;
The ids table doesn't seem to be needed for this query.

PostgreSQL - Select row with composite maximum value from 2 columns

I would like to select the best offers for a merchant in PostgreSQL 9.6 according some simple rules:
An offer is better than another if its discount value is greater regardless the benefit type
If the discount values are equal, then the one with benefit type ALL beats the one with FOOD
If both discount and benefit type are the same, then any offer can be selected e.g. pick the first one
So best is not just a max() call but a "conditional" max() where another column should be inspected too to determine which row it is.
Could you please help?
Schema:
create table offer (
id bigserial not null,
discount int4,
benefit_type varchar(25),
...
merchant_id int8 not null
);
Query (partial):
select merchant_id, max(discount) as max_discount
from offer
group by merchant_id;
Sample offers in DB:
id discount benefit_type ... merchant_id
0 10 FOOD 0
1 20 FOOD 0
2 20 ALL 0
3 30 ALL 1
4 40 ALL 1
5 40 FOOD 1
6 40 ALL 2
7 50 FOOD 2
Desired result set:
merchant_id max_discount benefit_type
0 20 ALL
1 40 ALL
2 50 FOOD
Merchant 0's best offer is offer 2 because 20 ALL > 20 FOOD.
Merchant 1's best offer is offer 4 because 40 ALL > 30 ALL.
Merchant 2's best offer is offer 5 because 50 FOOD > 40 ALL.
This can be achieved using distinct on() and a custom sort definition for the benefit_type:
select distinct on (merchant_id) *
from offer
order by merchant_id,
discount desc,
case when benefit_type = 'ALL' then 1 else 2 end;
This prefers higher discount. If two discounts are the same, a benefit_type of ALL is used as the tie-breaker.
Online example: http://rextester.com/TFBP17217

Efficient ways to count the number of times two items are ordered together

I am currently stuck on a problem where I have to write a SQL query to count the number of times a pair of items is ordered together.
The table that I have at my disposal is something like:
ORDER_ID | PRODUCT_ID | QUANTITY
1 1 10
1 2 20
1 3 10
2 1 10
2 2 20
3 3 50
4 2 10
I am looking to write a SQL query that can, for every unique pair of items, count the number of times they were ordered together and tell me the quantities when they were in the same order.
The resulting table should look like:
PRODUCT_ID_1 | PRODUCT_ID_2 | NUM_JOINT_ORDERS | SUM_QUANTITY_1 | SUM_QUANTITY__2
1 2 2 20 40
1 3 1 10 10
2 3 1 20 10
Some things to exploit are that:
Some orders only contain 1 item and so are not relevant in counting the pairwise relationship (not sure how to exclude these but maybe it makes sense to filter them first)
We only need to list the pairwise relationship once in the final table (so maybe a WHERE PRODUCT_ID_1 < PRODUCT_ID_2)
There is a similar post here, though I have reposted the question because
I really want to know the fastest way to do this since my original table is huge and my computational resources are limited, and
in this case I only have a single table and no table that lists the number.
You may use the following approach, which gives you the result shown above.
select
PRODUCT1, PRODUCT2, count(*), sum(QUANTITY1), sum(QUANTITY2)
from (
select
T1.PRODUCT_ID AS PRODUCT1,
T2.PRODUCT_ID AS PRODUCT2,
T1.QUANTITY AS QUANTITY1,
T2.QUANTITY AS QUANTITY2
from TABLE as T1, TABLE as T2
where T1.ORDER_ID=T2.ORDER_ID
and T1.PRODUCT_ID<T2.PRODUCT_ID
)
group by PRODUCT1, PRODUCT2