need an additional column in SQL output - sql

I have a table called product_info where there are two columns(product, product_id).There are 5 'product_id' and 10 'product'. I wrote the following code to list products and their count.Now I need to create an additional column called 'favorite_product' if the 'product' count is more than 3.When I tried with a couple of WHERE clause options, it filtered out my existing column (product_count) which I need to keep intact in the output. How can I do that?
Any help would be appreciated.
SELECT product AS Product_Name,
COUNT (product) AS Product_Count
FROM product_info
GROUP BY product

Just use a case expression:
SELECT product AS Product_Name, COUNT(*) AS Product_Count,
(CASE WHEN COUNT(*) > 3 THEN 1 ELSE 0 END) as is_favorite_flag
FROM product_info
GROUP BY product;

Related

SQL Pivot column values

I have tried following this and this(SQL Server specific solution) but were not helpful.
I have two tables, Product and Sale and I want to find how many products are sold on each day. But I want to pivot the table so that columns become the products name and each row will contain the amount of products sold for each day ordered by the day.
Simplified schema is as following
CREATE TABLE product (
id integer,
name varchar(40),
price float(2)
);
CREATE TABLE sale(
id integer,
product_id integer,
transaction_time timestamp
);
This is what I want
I only managed to aggregate the total sales per day per product but I am not able to pivot the product names.
select date(sale.transaction_date)
, product.id
, product.name
, count(product_id)
from sale inner join
product on sale.product_id = product.id
group by date(sale.transaction_date)
, product.id
, product.name
This is the situation so far
Please suggest.
You need pivoting logic, e.g.
select
s.transaction_date::date,
count(case when p.name = 'intelligent_rubber_clock' then 1 end) as intelligent_rubber_clock,
count(case when p.name = 'intelligent_iron_wallet' then 1 end) as intelligent_iron_wallet,
count(case when p.name = 'practical_marble_car' then 1 end) as practical_marble_car
from sale s
inner join product p
on s.product_id = p.id
group by
s.transaction_date::date;
Since your expected output aggregates by date alone, then only the transaction date should be in your GROUP BY clause. The trick used here is to take the count of a CASE expression which returns 1 when the record is from a given product, and 0 otherwise. This generates conditional counts for each product, all in separate columns. To add more columns, just add more conditional counts.

Determining if a sample contains 0 rows for multiple ID's

So I've created a simple query that will pass all OrdID's that have orders of 2 or more apples:
SELECT ordid
FROM results
WHERE ordid IN (12,24,53,21,41,51)
AND product = 'apples'
GROUP BY ordid
HAVING COUNT(ordid) > 1
How can I do this for OrdID's that contain 0 apples?(This doesn't work as there is no product on the OrdID by apples, so it passes 0 rows.) I'd like it to list all OrdID's that have < 1 products for Apples.
SELECT ordid
FROM results
WHERE ordid IN (12,24,53,21,41,51)
AND product = 'apples'
GROUP BY ordid
HAVING COUNT(ordid) < 1
I cannot reproduce in my machine but I hope that this query should work:
SELECT ordid
FROM results
WHERE ordid in (12,24,53,21,41,51)
GROUP BY ordid
HAVING SUM(CASE WHEN product = 'apples' THEN 1 ELSE 0 END) < 1
I switched the HAVING with a COUNT() of the products instead of the orderid since youre trying to count the number of products.
SELECT ordid
FROM results
WHERE ordid in (12,24,53,21,41,51) and product = 'apples'
GROUP BY ordid
HAVING COUNT(product) = 0
The problem you're running into is that you're selecting FROM a table (i.e., limiting to those rows) where what you want to match is what's not in the table (i.e., excluding those rows). These are opposites.
Instead, flip that around so you're selecting FROM the set of values and then excluding those that match:
SELECT ordid FROM (VALUES (12),(24),(53),(21),(41),(51)) AS ordids(ordid)
WHERE NOT EXISTS (
SELECT * FROM results
WHERE results.ordid = ordids.ordid
AND results.product = 'apples'
)
This will return a result for an ordid even if that value never appears in the results table at all.
Use the EXISTS() function to get all OrdIDs WHERE there does NOT EXIST a correlated row with product = 'apples'

Redshift - Finding number of times a flag appears for a particular ID

I have some sales data that shows if a bill has been generated for a customer. The column labelled bill_generated returns 'Y' if a bill has been generated else its blank. I am trying to find the list of customers for whom atleast one bill has been generated. There could be multiple rows for each cust_id as shown below:
cust_id, bill_generated
001,NULL
001,Y
002,NULL
002,NULL
003,Y
Could anyone advice on this. I am using Redshift DB. Thanks..
Try below using group by and having cluse
select cust_id from tablename
group by cust_id
having sum(case when bill_generated is null then 0 else 1 end)=1
you can use co-related sub-query
select * from t
where exists (select 1 from t t1
where t1.bill_generated='Y' and t1.cust_id=t.cust_id
)

Return a Complete sales order where a given item is purchased SQL

I'm trying to query our Sales_Order_Line_Item table. We are introducing a new "Tariff" Item code, our sales staff are required to add this code to all orders that have items that start with "WI". So I need to create a query that will show me any orders that have item codes that start with "WI" but are missing the "Tariff" code.
I can't seem to figure out how to return a list that shows this data.
For simplicity, my Sales_Order_Line_Item Table has these 3 columns:
UNIQUE_LINE_ID, SALE_ORDER_#, ITEM_#
One dirty trick is to use a case expression and count the number of times these items appear:
SELECT sale_order_no
FROM sales_order_line_item
GROUP BY sale_order_no
HAVING COUNT(CASE WHEN item_code LIKE 'WI%' THEN 1 END) > 0 AND
COUNT(CASE WHEN item_code = 'Tarrif' THEN 1 END) = 0
Should be something like this:
select * from Sales_Order_Line_Item
where ItemCode like 'wi%'
and tariff is null
If, you want full order details you can use EXISTS/NOT EXISTS instead :
select so.*
from sales_order_line_item so
where exists (select 1 from sales_order_line_item sol where sol.sale_order_no = s.sale_order_no and sol.item_code LIKE 'WI%') and
not exists (select 1 from sales_order_line_item sol where sol.sale_order_no = s.sale_order_no and sol.item_code = 'Tarrif');

getting different column names from 2 tables in sql server

I have Item and Sales tables with different columns like,
Item
ItemName
Itemcost
ItemQty
Sales
SalesName
SalesDate
SalesQty
In the above tables there is not common column,but i need to get output as
ItemName,ItemCost,SalesName,SalesDate.
I tried with union,
select ItemName,ItemCost from Item
union
select SalesName,SalesDate from Sales
but am getting only 1 table columns like ItemName,ItemCost
Please help me on this issue
Thanks In Advance
Venkat.
Use below sql query :
select i.ItemName, i.ItemCost, s.SalesName, s.SalesDate
from Item as i, Sales as s;
Use the below query :
This will join every row in table1 with table2 (the Cartesian product) returning all columns.
Select im.ItemName, im.ItemCost, sl.SalesName,sl.SalesDate from Item as im, Sales as sl;