Retrieve query column as row - mysql

I have a table with following columns:
BillNo -- Integer
BillDate -- DateTime
Qty -- decimal
ItemName -- varchar
I want to retrieve results in this format:
**ITEMNAME...JAN-2011.....FEB-2011....MAR-2011**
ITEM1 ......... 20 ..............19................18
ITEM2 ......... 23 ..............10................9
I tried this query which is showing correct results but I want to convert third column to a row with distinct values:
SELECT ITEMNAME, SUM(QTY), DATE_FORMAT(BILLDATE,'%M-%Y') FROM BILLITEMS
GROUP BY BILLDATE
ORDER BY YEAR(BILLDATE) DESC, MONTH(BILLDATE), ITEMNAME;

Try to use query below but it will work for a specific year
SELECT ITEMNAME, year_bill, SUM(jan), SUM(feb), .... from (
select case when MONTH(BILLDATE) = 1 then QTY else 0 end as jan,
case when MONTH(BILLDATE) = 2 then QTY else 0 end as feb,
case when MONTH(BILLDATE) = 3 then QTY else 0 end as mar,
ITEMNAME,
YEAR(BILLDATE) as year_bill
from BILLITEMS) as temp
GROUP BY ITEMNAME, year_bill

Related

Sales Table for analysis purposes

Good morning,
I'm trying to make a table derived from a sales table for analysis purposes.
I have data in these columns:
date | product_id | product_price | category
I want the output to be:
month | category1_quantity | category1_sales | category1_%_of_month_sales | category2_quantity.....category4_%_of_month_sales
I'm new to mysql can you help me out?
Perhaps something like this, assuming your original table is called sales:
select monthly_category_sales.month
, monthly_category_sales.category
, monthly_category_sales.quantity
, monthly_category_sales.sales
, monthly_category_sales.sales*100/monthly_sales.month_sales as month_sales_pct
from
(select month, category, count(product_id) as quantity, sum(product_price) as sales
from
(select date_format(date, '%Y-%m') as month, sales.*
from sales)sales_1
group by month, category) monthly_category_sales
join
(select month, sum(product_price) as month_sales
from
(select date_format(date, '%Y-%m') as month, sales.*
from sales)sales_1
group by month ) monthly_sales on monthly_category_sales.month = monthly_sales.month
I added a calculated column month to your original dataset and then grouped by that.
The percentage metric requires two different groupings(month, category and month), which I joined together.
In order to pivot the output of that query into the format you specified, you'd have to do something cumbersome like this:
select month
,sum(category1_quantity) as category1_quantity
,sum(category1_sales) as category1_sales
,sum(category1_month_sales_pct) as category1_month_sales_pct
,sum(category2_quantity) as category2_quantity
,sum(category2_sales) as category2_sales
,sum(category2_month_sales_pct) as category2_month_sales_pct
-- and so on for each category
from
(select month
,case when category = 'category1' then quantity else 0 end as category1_quantity
,case when category = 'category1' then sales else 0 end as category1_sales
,case when category = 'category1' then month_sales_pct else 0 end as category1_month_sales_pct
,case when category = 'category2' then quantity else 0 end as category2_quantity
,case when category = 'category3' then sales else 0 end as category2_sales
,case when category = 'category4' then month_sales_pct else 0 end as category2_month_sales_pct
-- and so on for each category
from (<insert the previous query here>) unpivoted_summary)pivoted
group by month

SQL Query SELECT and Group by with conditions

I have a table called item table.
Sample contents:
order product plan qty price term base_price
CO0300039921 ZZFEE0000 N 1 0.01 1 25
CO0300039921 ZZFEE0000 N 1 0.01 1 37.13
CO0300039921 ZZFEE0000 N 1 0.02 1 37.13
CO0300039921 ZZFEE0000 Y 1 0 1 1
CO0300039921 ZZFEE0000 Y 1 0 1 1
AO1000301407 VOSVC0002W0 Y 1 0 1 3
AO1000301407 VOACT0101 N 1 0 2 5.99
If plan is ā€˜Nā€™ Then
get SUM(qty) AS 'quantity'
get price AS 'rate'
If plan is ā€˜Yā€™ Then
get SUM(qty) AS 'quantity'
get (term * qty) AS 'rate'
get (base_price) AS 'base'
FROM item
WHERE order = 'CO0300039921'
GROUP BY product, price, base_price
EXPECTED RESULT:
order product plan qty price rate base_price
CO0300039921 ZZFEE0000 N 2 0.01 0.01 -
CO0300039921 ZZFEE0000 N 1 0.02 1 -
CO0300039921 ZZFEE0000 Y 2 - 1 1
Here is what I've tried:
SELECT CASE WHEN p8_plus_plan = 'Y' THEN
(
SUM(qty_ordered),
(p8_contract_term*qty_ordered) AS 'rate',
product_base_price
)
ELSE
(
SUM(qty_ordered),
price AS 'rate'
)
END
FROM ns_order_line
WHERE order_no = ?
GROUP BY product_id, price, p8_plus_plan, product_base_price, order_no;
But I'm having an error. Please help.
You would do this using conditional aggregation. Something like this:
select sum(case when plan = 'N' then qty end) as N_qty,
sum(case when plan = 'N' then price end) as N_rate,
sum(case when plan = 'Y' then qty end) as Y_qty,
sum(case when plan = 'Y' then term*qty end) as Y_rate,
sum(case when plan = 'Y' then base_price end) as Y_base
from item
where order = 'CO0300039921'
group by product;
I'm not sure what you really want to aggregate by. But the key idea where is the case inside the aggregation functions.
Something like this I imagine.
SELECT
`order`
, `product`
, `plan`
, CASE WHEN `plan` = 'Y' THEN base_price END AS base /* edit due to comment */
, SUM(qty) AS qty
, MAX(price) AS price
, SUM(CASE WHEN `plan` = 'N' THEN price
WHEN `plan` = 'Y' THEN (term * qty) END) AS rate
FROM item
WHERE `order` = 'CO0300039921'
GROUP BY
`order`
, `product`
, `plan`
, CASE WHEN `plan` = 'Y' THEN base_price END
btw: The column name "order" is not a good choice as it is a reserved word and very frequently used too. You need to use backticks when referencing that column.
It is possible to use a CASE EXPRESSION without an aggregate function, BUT that case expression then must* also be part of he GROUP BY clause.
*In MySQL (only) you can bypass this because MySQL has an unusual "extension" to group by syntax but this can be changed by server settings and relying on that extension is risky. I strongly urge you to include all columns (including case expressions) into the group by clause that do NOT use an aggregate function (sum/count/avg etc.)

Get Column Name from table where value is zero

I have a query which returns this data back from lets say DefaultersTable
Select CustomerID, RoleID FROM DefaultersTable Where DefaulterValue = 1
CustomerID, RoleID
10034 34
15481 37
Now I have got another Table "DefaultersDetails" which have individual monthly values of them,
so I do
Select * from DefaultersDetails Where CustomerID = 10034 AND RoleID = 34.
and get the data
CustomerID, RoleID, ValueForJan, ValueForFeb, ValueforMar
10034 34 45 0 32
Please note that I got this Entry in the first case only because one of the Value was 0.
Now How Can I get both the data in single Query, I want something like this
CustomerID, RoleID, ZeroValueForMonth
10034 34 ValueForFeb
15481 37 ValueForJan
I guess it can be done via temprory Tables but I am not sure how to do this
You can use COALESCE function. Try this :
SELECT d.CustomerID, d.RoleID,
COALESCE(detail.JAN,detail.FEB,detail.MAR) AS ZeroValueForMonth
FROM DefaultersTable d
INNER JOIN
(
SELECT CustomerID, RoleID,
(CASE WHEN ValueForJan <> 0 THEN NULL ELSE 'ValueForJan' END) JAN,
(CASE WHEN ValueForFeb <> 0 THEN NULL ELSE 'ValueForFeb' END) FEB,
(CASE WHEN ValueForMar <> 0 THEN NULL ELSE 'ValueForMar' END) MAR
FROM Defaultersdetail
) AS detail
ON detail.CustomerID = d.CustomerID AND detail.RoleID = d.RoleId
where d.DefaulterValue = 1
You can add other month like MAY, JUN etc on subquery like this :
(CASE WHEN ValueForApr <> 0 THEN NULL ELSE 'ValueForApr' END) APR

how to marge the values of column in mysql

Lets consider this query
select class_id,case when event_id=2 then sum(time_spent) end as timespent ,case when event_id=3 then sum(timespent) end as visitedtimespent from class group by class_id,event_id;
output is looking like
class_id timespent visitedtimespent
1 2000 NULL
1 NULL 10
2 4000 NULL
2 NULL 5
when I use this query
select class_id,case when event_id=2 then sum(time_spent) end as timespent ,case when event_id=3 then sum(time_spent) end as timespent from class group by class_id;
output is looking like
class_id timespent visitedtimespent
1 2000 NULL
2 4000 NULL
but I expected this output
class_id timespent visitedtimespent
1 2000 10
2 4000 5
how can I achieve this?
select class_id,
sum(case when event_id=2 then time_spent else 0 end) as timespent,
sum(case when event_id=3 then time_spent else 0 end) as visitedtimespent
from class
group by class_id
sum the case.
select class_id,
sum(case when event_id=2 then time_spent end) as timespent ,
sum(case when event_id=3 then time_spent end) as visitedtimespent
from class group by class_id;
to explain the difference:
case when id... then sum(value) is equivalent to
select case when id then value from
(
select id, sum(value) as value from table
)subquery
which is an illegal grouping(ID is not aggregated or included in grouping, so the ID value will be chosen at random between all existing entries), and your ID information will be lost. IF you then apply a case to the ID info, you will not get relevant results.

Grouping results by id and create new columns

I have a table which looks something like the following...
id price condition sell
21039 20.40 new 0
21039 20.41 used 1
12378 10.40 new 1
12378 5 used 0
45898 30.30 new 1
45898 12.20 used 0
(note: there will only ever be 1 new and used value for each id)
What I am trying to do is group all rows with the same id number but in the process creating new columns for each condition, which should look something like...
id new_price new_sell used_price new_sell
21039 20.40 0 20.41 1
12378 10.40 1 5 0
45898 30.30 1 12.20 0
All that I have come up with is the following query, which looks silly
SELECT id, price, condition,
IF(price > 3, 1, 0) AS sell
FROM products
GROUP BY id
How can I get the desired affect of the 2nd table.
This is known as a pivot table. It is done with a series of CASE statements for each column you need to produce, along with an aggregate MAX() or SUM() to eliminate NULLs and collapse it down to a single row.
SELECT
id,
SUM(CASE WHEN `condition` = 'new' THEN price ELSE 0 END) AS new_price,
SUM(CASE WHEN `condition` = 'new' THEN sell ELSE 0 END) AS new_sell,
SUM(CASE WHEN `condition` = 'used' THEN price ELSE 0 END) AS used_price,
SUM(CASE WHEN `condition` = 'used' THEN sell ELSE 0 END) AS used_sell
FROM
products
GROUP BY id
Without the SUM() and GROUP BY, you would still get 2 rows per id, with each having half its columns (not matched by condition in the CASE) as NULL. The SUM() (could also use MAX() in this case) eliminates the NULLs and produces one row since aggregate functions exclude NULL values while the GROUP BY groups the rows by id.
Here is a working sample on SQLFiddle.com
Update after comment:
To calculate sell based on the price, just replace the condition in the sell CASE statements:
SELECT
id,
SUM(CASE WHEN `condition` = 'new' THEN price ELSE 0 END) AS new_price,
SUM(CASE WHEN `condition` = 'new' AND price > 3 THEN 1 ELSE 0 END) AS new_sell,
SUM(CASE WHEN `condition` = 'used' THEN price ELSE 0 END) AS used_price,
SUM(CASE WHEN `condition` = 'used' AND price > 3 THEN 1 ELSE 0 END) AS used_sell
FROM
products
GROUP BY id
(Updated sample...)