I need to find items that contain SKUs starting with AB but would still want the query to return orders that contains AB and others.
order number 12334: sku AB12 & AB24
order number 22356: sku AB523 & KC5145
order number 123556: sku CD5641 & BG521
I expect the query to return order number 12334 and 22356 but not 123556
I would also like to know if an order is purely AB or AB with other items
so the table would return count of orders that contains only AB and count of order that contains AB with other items.
I have two tables: an orders table and line_items
orders table gives order_id to link to line_items table ID
select * from xx.line_items l
left join xx.orders o on l.order_id=o.id
where sku like 'AB%'
You haven't shared much details about the tables and columns for us to provide the full solution, but see if you can build something off of this mock up
select
sku,
(char_length(sku)-char_length(replace(sku,'AB','')))/2 as item_count
from your_table
where sku like '%AB%';
he following query gives you all order IDs with AB items. It shows their AB count and their total count, so you can compare the two. You could also add a CASE WHEN expression to compute a flag showing whether the order is pure AB or not.
After all this simply groups the items per order, counts AB items and dismisses all orders that have no AB item.
select
order_id,
count(*) as count_all,
count(case when sku like 'AB%' then 1 end) as count_ab
from line_items
group by order_id
having count(case when sku like 'AB%' then 1 end) > 0;
You can replace count(case when sku like 'AB%' then 1 end) with sum(sku like 'AB%') in MySQL by the way.
Here is a query building up on the above to count pure AB orders and mixed orders:
select (count_all = count_ab) as ab_only, count(*)
from
(
select count(*) as count_all, count(case when sku like 'AB%' then 1 end) as count_ab
from line_items
group by order_id
having count(case when sku like 'AB%' then 1 end) > 0
) counted
group by (count_all = count_ab);
Related
I am having one table in SQL Database where I record customer wise sales for specific products. I have monthly target for each product like as below
Product A - 50 pcs
Now in my table I am seeing customer wise sales and the monthly product sale target which is common.
Customer Product MonthlyTargetQty
Customer A Product 1 50
Customer B Product 1 50
Customer C Product 1 50
Customer D Product 1 50
I want to keep only distinct value in MonthlyTargetQty Column and do not want to delete Product name which is repeating in Product Column. Please help with a query
How I want it is : -
Customer Product MonthlyTargetQty
Customer A Product 1 50
Customer B Product 1 0
Customer C Product 1 0
Customer D Product 1 0
You seem to want:
select customer, product,
(case when row_number() over (partition by product order by customer) = 1 then monthlytargetqty end) as monthlytargetqty
from t
order by product, customer;
This uses row_number() to define the first row for each customer and then a case expression to keep the value you want on that row. Note that the order by is consistent with the partition by/order by for row_number().
EDIT:
If you want to update the existing table -- which seems like a really bad idea to me -- you can do:
update t join
(select product, min(customer) as min_customer
from t
group by product
) tt
on t.product = tt.product and t.customer <> tt.min_customer
set monthlytargetqty = 0;
from the comment it seems you want update I added with update
with cte as
(
select customer, product,
(case when row_number() over (partition by product order by customer) = 1 then monthlytargetqty end) as monthlytargetqty
from t
)
update a
set a.MontylyTargetQty= b.monthlytargetqty
from ProductAnalysisTable a join cte on
a.customer=cte.customer and a.product=b.product
btw 1st part is sir #gordon so accept his answer
I have a products in products table with status broken or not broken.
I need an sql query which show
productid, total no of this this item is in table , times its status was one,
e-g product_id | tottal_no_of_products_oF_this_type | broketn
5 10 | 3
SELECT product_id,
COUNT(product_id) AS duplicate_column, product_status
FROM products_stored where product_status=broken
GROUP BY product_id
ORDER BY COUNT(product_id) DESC;
You are close. You can get the broken ones using conditional aggregation. For example:
select
product_id,
count(*) as total_no_of_products_this_type,
sum(case when product_status = 'broken' then 1 else 0 end as broken
from products_stored
group by product_id
order by count(*) desc
try this :
SELECT product_id,
COUNT(product_id) over(partition by product_status) AS duplicate_column, product_status
FROM products_stored where product_status=broken
ORDER BY 2 DESC;
I would like to start by explaining what my query should do.
At my store,we sell products A,B,C and D(Product ID)
Let's say I am interested in only those transactions where Item A was sold
This is how i wrote my query
Select [Transaction_No],[Product ID]
from [MystoreDB$Transaction lines]
where Date = '01-Jan-2016'
and (Product ID) = 'A'
The query executes without any errors,and I get the results only filtered to Product ID A.
But if I really look into the filtered transactions, I can see that there were other products bought in the same transaction(Product B was bought as well)
But the query only filtered 'the rows' with Product A
For Instance
There were total of 4 transactions done on 1-Jan-2016
Transaction 1 had
Product A + B
Transaction 2 had
Product A only
Transaction 3 had
Product A + C
Transaction 4 had
Product A only
At the end I want my query to retrieve only 2 transactions
Which is Transaction 2 and 4(since only product A was purchased)
I will ignore Transactions 1 and 3 since another product was purchased along with product A
What I want to find out is all transactions that had only Product A.
This means, the customer only bought product A and no other products.
Not sure how to get this.
I am using MYSQL for the DB engine
SELECT
Transaction_No
FROM
Transactions
WHERE
Date = '01-Jan-2016'
GROUP BY
Transaction_No
HAVING
COUNT(CASE WHEN Product_Id = 'A' THEN Product_Id END) = COUNT(*)
Doing a group by with conditional aggregation will give you the desired result and as there are no sub selects etc it should preform faster than a NOT EXISTS solution.
Edit Per Your Comment:
To test to see if a customer bought both Product A & B but no other products you would have to add a couple of additional constraints in your HAVING clause. Test that COUNT of A > 0 and COUNT of B > 0 and then that the COUNT of A & B is the same as the COUNT of All Products.
SELECT
Transaction_No
FROM
Transactions
WHERE
Date = '01-Jan-2016'
GROUP BY
Transaction_No
HAVING
COUNT(CASE WHEN Product_Id = 'A' THEN Product_Id END) > 0
AND COUNT(CASE WHEN Product_Id = 'B' THEN Product_Id END) > 0
AND COUNT(CASE WHEN Product_Id IN ('A','B') THEN Product_Id END) = COUNT(*)
Add this to your WHERE clause:L
AND [Transaction_No] NOT IN (
SELECT [Transaction_No]
FROM [MystoreDB$Transaction lines]
where [Product ID] <> 'A'
)
to exclude customers who bought some other product.
I'm trying to write a query to count the customers that purchased at least one from order_type=0 and one order_type=1 during the same month in 2014
I have two tables.
The order table that have:
order_id
customer_id
aquisition_date
orders_category table:
order_id
order_type (the type of the orders it may have 0, 1, 2, 3, 5, 8 ...etc )
I tried with this query but it didn't work, I know it's not complete and I missed the month condition!
Select count(user_id) From order
join orders_category
on order.order_id = orders_category.order_id
Where (order_type=0 or order_type=1)
and extract (year from order.aquisition_date)=2014
group by user_id
having count (case when type_id=0 then null else null end) > 0
and count (case when type_id=1 then null else null end) > 0;
I don't know how to find users with at least 1 order from order_type=0 & 1 order of order_type=1, in the same month.
You could use this query, based on what you already had. However, I suggest you change the name of the table order to orders as order is a reserved word:
select count(distinct user_id)
from (
select user_id, month(aquisition_date)
from orders
inner join order_category
on orders.order_id = order_category.order_id
where order_type in (0, 1)
and year(aquisition_date) = 2014
group by user_id, month(aquisition_date)
having count(distinct order_type) = 2
) as base
SQL fiddle
I selected the month also in the sub-select, as it will be interesting to look at the output of that query on its own during your analysis.
I'd like to count the number of purchases of each item while also, depending on who's viewing the content, show whether the user has purchased the content. Because the number of items and purchases could become large I'm reluctant to throw in more JOINs to accomplish this because that would seem not performant.
Basically, I'd like to have a did_i_buy field somewhere in the following query without adding another JOIN. Is this possible? Let's say for user_name=tom:
SELECT Items.item_id, item_name, COUNT(purchase_status='bought') as number_bought
FROM Purchases
JOIN Items ON Purchases.item_id=Items.item_id
GROUP BY Items.item_id
Here's my DB structure:
Table Items
item_id item_name
1 item_1
2 item_2
3 item_3
Table Purchases
item_id purchase_status user_name
1 bought joe
2 bought joe
1 bought tom
1 bought bill
Desired result for tom
item_id item_name number_bought did_i_buy
1 item_1 3 yes
2 item_2 1 no
If I understand correctly, the did_i_buy column means "did Tom buy". You can do that like this:
SELECT
Items.item_id,
item_name,
COUNT(CASE WHEN purchase_status='bought' THEN 1 END) as number_bought,
MAX(CASE WHEN purchase_status='bought' AND user_name='Tom' THEN 'yes' ELSE 'no' END) AS did_i_buy
FROM Purchases
JOIN Items ON Purchases.item_id=Items.item_id
GROUP BY Items.item_id
Alternatively (one CASE statement, see comments below)
SELECT
Items.item_id,
item_name,
COUNT(purchase_status='bought') as number_bought,
MAX(CASE WHEN user_name='Tom' THEN 'yes' ELSE 'no' END) AS did_i_buy
FROM Purchases
JOIN Items ON Purchases.item_id=Items.item_id
WHERE purchase_status='bought'
GROUP BY Items.item_id
And one more tweak: Because of the WHERE clause, the COUNT is only going to see rows where purchase_status='bought', so the expression checking the status can be left out (the only change from above is in line 4):
SELECT
Items.item_id,
item_name,
COUNT(*) as number_bought,
MAX(CASE WHEN user_name='Tom' THEN 'yes' ELSE 'no' END) AS did_i_buy
FROM Purchases
JOIN Items ON Purchases.item_id=Items.item_id
WHERE purchase_status='bought'
GROUP BY Items.item_id
You must (I think) use subqueries. Each request for a count is a separate query, so there is no way to optimize this (except to compress it all into one query with subqueries). There is no special relation between the horizontal data in items with the vertical data in purchases.
Here is an example query to count transactions for users:
SELECT user_id,(SELECT count(*) FROM transactions WHERE buyer_id=u.user_id) as count FROM users as u
I did a comparison with this query versus a similar query of the other JOIN type. The result: 0.0005 for this one vs. 0.0018 Ed Gibbs. However, if sorting of the number_bought (ORDER BY count DESC) is required, the latter query is significantly faster.