Prefered results - sql

I am trying to list all DEPARTMENT_IDs with PRODUCT_IDs, first where PRODUCT_COST_STATUS = 1 but there are also data with where PRODUCT_COST_STATUS = 0. I prefer to list first "1"s and if not then "0"s with the latest date (this is another case for future) ... The code I wrote should give the expected result but it takes a lot of time to run query. I don't to want to list duplicate DEPARTMENT_ID.
Is there any way around ?
Thanks
SELECT PRODUCT_ID
,PRODUCT_COST_STATUS
,DEPARTMENT_ID FROM [PRODUCT_COST] PC
WHERE PRODUCT_COST_STATUS = 1
OR PRODUCT_ID NOT IN (SELECT PRODUCT_ID
FROM
[PRODUCT_COST]
where PRODUCT_COST_STATUS = 0
GROUP BY PRODUCT_ID,
PRODUCT_COST_STATUS,
DEPARTMENT_ID) GROUP BY PRODUCT_ID,
PRODUCT_COST_STATUS,
DEPARTMENT_ID
ORDER BY PRODUCT_ID,
DEPARTMENT_ID

I solved with the help of my friend and wanted to share here...
PRODUCT_COST_STATUS is a bit
SELECT PRODUCT_ID
,DEPARTMENT_ID
,LOCATION_ID
,max(cast(PRODUCT_COST_STATUS as int)) as maxpcs
,max(ACTION_DATE) as maxad
FROM [PRODUCT_COST]
group by
PRODUCT_ID, DEPARTMENT_ID,LOCATION_ID

Related

How to get a fraction of counters of subquery from different subqueries in one select?

I have a table with reviews for products. I want to sort product_ids that have more than 100 verified reviews(verified review is a review with verified_purshace=True) by the fraction of 5 star-reviews to all reviews. I tried to implement this in one select, but after numerous tries, I finish with the need to create views. I managed to write a query that counts a number of 5-star reviews, but can`t do better. Can anybody give me a hint?
My best query:
select *,count(*)
from (
select *
from reviews
where star_rating = 5
) low_reviews
left join (
select distinct filtered_reviews.product_id
from (
select *
from (
select verified_reviews.product_id, count(*) as verified_reviews_number
from (
select *
from reviews
where verified_purchase=True
) as verified_reviews
) as counted_verified_reviews
where counted_verified_reviews.verified_reviews_number > 100
) as filtered_reviews
) filtered_product_ids on low_reviews.product_id = filtered_product_ids.product_id;
Data example:
review_id customer_id product_id star_rating helpful_votes total_votes vine verified_purshase review_headline review_body review_date
14830128 R158AS05ZMH7VQ 0615349439 5 2 2 N false Planting a Church ... Witnessing To Dracula... 2011-02-14
I want to sort product_ids that have more than 100 verified reviews(verified review is a review with verified_purshace=True) by the fraction of 5 star-reviews to all reviews.
You don't provide sample data, but I would expect a query like this:
select product_id
from reviews
where verified_purchase
group by product_id
having count(*) > 100
order by avg( (review = 5)::int ) desc;
The expression avg( (review = 5)::int ) is a shorthand way of saying count(*) filter (where review = 5) * 1.0 / count(review). It works because it converts the expression review = 5 to an int, which is 1 for true and 0 for false. The average is the proportion of times when it is true.
Actually, the above assumes that you only care about review start ratings for verified purchases. If you want to include all reviews (even non-verified ones) for the ordering:
select product_id
from reviews
group by product_id
having count(*) filter (where verified_purchase) > 100
order by avg( (review = 5)::int ) desc;

Group by, then select only records where every value of a boolean column is true

I have both a MS SQL Database and a postgres database. A solution in either will work as I can translate it.
We have a customer_phone table where the relevant columns are:
id, customer_id, phone, is_bad
What I need to do is select all the customer_id's from this table that ONLY have is_bad = true. So if you have 1 good phone number and 1 bad, you shouldn't appear.
For some reason I'm struggling to find an easy way to do this, I feel like it should be deceptively simple.
This was a start that gives me at least all the customers a count of their good and bad numbers, but I'm wondering if there is a way that doesn't involve having to use subqueries and in's?
select customer_id, is_bad, count(customer_id)
from customer_phone cp
group by customer_id, is_bad
order by customer_id desc
The most intuitive way I've found to add over a boolean column like this is to SUM a column which is 1 when TRUE and 0 when FALSE:
CASE WHEN some_bool THEN 1 ELSE 0 END
So in your case:
SELECT id
FROM phones
GROUP BY id
HAVING
SUM(CASE WHEN NOT is_bad THEN 1 ELSE 0 END) = 0
Check out this SQL fiddle which shows the query in action.
You could use the "aggregate function", bool_and.
This takes a set of inputs and returns:
true if all input values are true, otherwise false
In your case, where we want every is_bad to be true for a particular customer:
select customer_id
from customer_phone
group by customer_id
having bool_and(is_bad)
You can use NOT EXISTS:
select customer_id
,is_bad
,count(customer_id)
from customer_phone cp
where not exists(select 1 from customer_phone
where is_bad = true)
group by customer_id, is_bad
order by customer_id desc
;
You could use MIN to identify if there are only is_bad values. You just have to cast to Int first.
SELECT customer_id
FROM customer_phone cp
GROUP BY customer_id
HAVING MIN(cast(is_bad as int)) = 1;

Oracle SQL query, getting a a maximum of a sum

Hey, guys. I'm struggling to solve one query, just cant get around it.
Basically, I got a some tables from data mart :
DimTheatre(TheatreId(PK), TheatreNo, Name, Address, MainTel);
DimTrow(TrowId(PK), TrowNo, RowName, RowType);
DimProduction(ProductionId(PK), ProductionNo, Title, ProductionDir, PlayAuthor);
DimTime(TimeId(PK), Year, Month, Day, Hour);
TicketPurchaseFact( TheatreId(FK), TimeId(FK), TrowId(FK),
PId(FK), TicketAmount);
The thing I'm trying to achieve in oracle is - I need to retrieve the most popular row type in each theatre by value of ticket sale
Thing I'm doing now is :
SELECT dthr.theatreid, dthr.name, max(tr.rowtype) keep(dense_rank last order
by tpf.ticketamount), sum(tpf.ticketamount) TotalSale
FROM TicketPurchaseFact tpf, DimTheatre dthr, DimTrow tr
WHERE dthr.theatreid = tpf.theatreid
GROUP BY dthr.theatreid, dthr.name;
It does give me the output, but the 'TotalSale' column is totally out of place, it gives much way higher numbers than they should be.. How could I approach this issue :) ?
I am not sure how MAX() KEEP () would help your case if I understand the problem correctly. But the below approach should work:
SELECT x.theatreid, x.name, x.rowtype, x.total_sale
FROM
(SELECT z.theatreid, z.name, z.rowtype, z.total_sale, DENSE_RANK() OVER (PARTITION BY z.theatreid, z.name ORDER BY z.total_sale DESC) as popular_row_rank
FROM
(SELECT dthr.theatreid, dthr.name, tr.rowtype, SUM(tpf.ticketamount) as total_sale
FROM TicketPurchaseFact tpf, DimTheatre dthr, DimTrow tr
WHERE dthr.theatreid = tpf.theatreid AND tr.trowid = tpf.trowid
GROUP BY dthr.theatreid, dthr.name, tr.rowtype) z
) x
WHERE x.popular_row_rank = 1;
You want the row type per theatre with the highest ticket amount. So join purchases and rows and then aggregate to get the total per rowtype. Use RANK to rank your row types per theatre and stay with the best ranked ones. At last join with the theatre table to get the theatre name.
select
theatreid,
t.name,
tr.trowid
from
(
select
p.theatreid,
r.rowtype,
rank() over (partition by p.theatreid order by sum(p.ticketamount) desc) as rn
from ticketpurchasefact p
join dimtrow r using (trowid)
group by p.theatreid, r.rowtype
) tr
join dimtheatre t using (theatreid)
where tr.rn = 1;

How to count each instance where a certain product was sold after a different product? SQL or DAX

Sorry if the title seems confusing, it was the best I could come up with.
I can work with both excel(Dax since its a power query) and sql:
I have a situation where there are two product types being purchased, Type_A and Type_B.
I want to calculate a count of how many unique Loc_ID have purchased a "Type_A" Product type, AFTER purchasing a "Type_B" Product type.
From my example there are a total of 3 unique Loc_ID which would fall in this filter: Loc_01, Loc_02, and Loc_04
Any help is greatly appreciated
Try this (it works good if each loc_id purchased both type of products as in your example.
select count(*)
from
(select loc_id , max(date_purchased) dt
from table t where product_type = 'type_a'
group by loc_id) a,
(select loc_id , max(date_purchased) dt
from table t where product_type = 'type_b'
group by loc_id) b
where a.loc_id=b.loc_id and a.dt>b.dt;
This will work even if certain loc_id did not purchase both type of products
Try this:-
Select count(a.loc_id) as cnt_locations
from
your_table_name a
inner join
(
Select a.loc_id,b.date_purchased,b.Product_type
from
(
Select loc_id, min(date_purchased) as date_purchased
from
your_table_name
group by loc_id
) a
inner join
your_table_name b
on a.loc_id=b.loc_id and a.date_purchased =b.date_purchased
where Product_type ='Type_B'
) b
on
a.loc_id=b.loc_id
where a.date_purchased >b.date_purchased and a.Product_type ='Type_A'

select least row per group in SQL

I am trying to select the min price of each condition category. I did some search and wrote the code below. However, it shows null for the selected fields. Any solution?
SELECT Sales.Sale_ID, Sales.Sale_Price, Sales.Condition
FROM Items
LEFT JOIN Sales ON ( Items.Item_ID = Sales.Item_ID
AND Sales.Expires_DateTime > NOW( )
AND Sales.Sale_Price = (
SELECT MIN( s2.Sale_Price )
FROM Sales s2
WHERE Sales.`Condition` = s2.`Condition` ) )
WHERE Items.ISBN =9780077225957
A little more complicated solution, but one that includes your Sale_ID is below.
SELECT TOP 1 Sale_Price, Sale_ID, Condition
FROM Sales
WHERE Sale_Price IN (SELECT MIN(Sale_Price)
FROM Sales
WHERE
Expires_DateTime > NOW()
AND
Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition )
The 'TOP 1' is there in case more than 1 sale had the same minimum price and you only wanted one returned.
(internal query taken directly from #Michael Ames answer)
If you don't need Sales.Sale_ID, this solution is simpler:
SELECT MIN(Sale_Price), Condition
FROM Sales
WHERE Expires_DateTime > NOW()
AND Item_ID IN
(SELECT Item_ID FROM Items WHERE ISBN = 9780077225957)
GROUP BY Condition
Good luck!