How to query this output in SQL Server? - sql-server-2008

I have this data:
NAME AMOUNT TYPE
-------------------------------------------
Apple 100 Good
Orange 200 Good
Apple 300 Good
Orange 100 Damage
I need an output like this, with Total Amount = SUM(Damage) - SUM(Good):
NAME TOTAL AMOUNT
--------------------------
Apple 400
Orange 100

Name | Amount | Type
Apple | 100 | Good
Orange | 200 | Good
Apple | 300 | Good
Orange | 100 | Damage
SELECT t.Name as Name, SUM(t.Good) as Good, SUM(t.Damage) as Damage, SUM(t.Good) - SUM(t.Damage) as Total
from (
SELECT Name, SUM(Amount) as 'Good', 0 as 'Damage'
FROM `tb_name`
where Type = 'Good' group by Name
UNION
SELECT name, '0' as 'Good', SUM(Amount) as 'Damage'
FROM `tb_name`
where Type = 'Damage' group by Name) t
group by t.Name`;
OUTPUT
Name | Good | Damage | Total
Apple | 400 | 0 | 400
Orange | 200 | 100 | 100

select FruitName,
(select ISNULL(sum(amount),0)
from Fruit d
where d.FruitName=m.FruitName and d.Type='Good')
- (select ISNULL(sum(amount),0)
from Fruit d where d.FruitName=m.FruitName and d.Type='Damage')
as 'Total Amount'
from Fruit m
group by FruitName

Related

MySQL group by percent with where clause

i have a table Products
with following fields and values:
ID | Productname | Productprice | Supplier | Available |
+----+-------------+--------------+----------+-----------+
| 1 | Tshirt | 20 | CompanyA | Yes |
| 2 | Pants | 45 | CompanyA | Yes |
| 3 | Shoes | 95 | CompanyB | Yes |
| 4 | Socks | 12 | CompanyA | No |
| 5 | Trainer | 50 | CompanyA | Yes |
How to query how many products belong to CompanyA with status Available=Yes in percentage?
To get the percentage of available products appearing in CompanyA from the overall products, you may use a subquery to calculate that.
SELECT COUNT(*) * 100 / (SELECT COUNT(*) FROM `products`) as `percentage`
FROM `products` WHERE `supplier` = 'CompanyA' and `available` = 'Yes'
Based on your data sample, the above query should return
percentage
+-----+-------+
| 60.0000 |
Considering that by "percent" you mean the number of rows with Available among all rows of that company:
select Supplier, TotalAvailable / Total from(
select
Supplier,
sum( if(Available = 'Yes',1,0) ) as TotalAvailable,
count(*) as Total
from
Products
where
Supplier = 'CompanyA'
group by
Supplier
) a
Or you can use
select
Supplier,
sum( if(Available = 'Yes',1,0) ) / count(*) as Percent
from
Products
where
Supplier = 'CompanyA'
group by
Supplier
Mind that you must handle the "Percent" as it fits for your intentions: multiply by 100, cut the decimals for representation etc.

Mysql sum with group_concat and join tables

I've trying to solve this problem for about weeks now, but still have no answers
i want to show the total quantity of the inventory_table that has the same product barcode and show also its item description.
I have three tables
product_table
ID| barcode | brand | unit | price
1 | 1111111 | Neozep | Tablet | 5.50
2 | 2222222 | Biogesic | Syrup | 7.50
inventory_table
ID| batch | Total| barcode
1 | 5555555 | 100 | 1111111
2 | 6666666 | 500 | 1111111
productcontains_table
ID| Name | Amount | Type | barcode
1 | Paracetamol | 250 | mg | 1111111
2 | Amoxicilin | 20 | ml | 1111111
And the output should be like this
Barcode | Item Description | Price | Total Qty | Amount
1111111 | Paracetamol 250 mg | Amoxicilin 20 ml | P5.50 | 600 | P3300
My current Sql statement but this is obviously wrong hope you can help me guys
thanks in advance
SELECT
GROUP_CONCAT(DISTINCT productcontains_table.name ,' ',
productcontains_table.Amount,' ',
productcontains_table.Type
ORDER BY productcontains_table.IDno SEPARATOR ' | ' ) AS ItemDescription,
product_table.product_price AS Price,
SUM(inventory_table.inventory_total) AS TotalQuantity
product_table.price AS Price,
SUM(inventory_table.total) AS TotalQuantity,
product_table.price * SUM(inventory_table.total) AS TotalAmount
FROM inventory_table
JOIN product_table
ON product_table.barcode = inventory_table.barcode
JOIN productcontains_table
ON productcontains_table.barcode = product_table.barcode
GROUP BY inventory_table.barcode
Fixed a couple of typos:
SELECT inventory_table.barcode,
GROUP_CONCAT(DISTINCT productcontains_table.name,' ', productcontains_table.Amount,' ', productcontains_table.Type SEPARATOR ' | ') AS ItemDescription,
product_table.price AS Price,
SUM(inventory_table.total)/ b.cnt AS TotalQuantity,
product_table.price * SUM(inventory_table.total) / b.cnt AS Amount
FROM inventory_table
JOIN product_table ON product_table.barcode = inventory_table.barcode
JOIN productcontains_table ON productcontains_table.barcode = product_table.barcode
JOIN
( SELECT barcode,
count(productcontains_table.name) AS cnt
FROM productcontains_table )b ON b.barcode=product_table.barcode
GROUP BY inventory_table.barcode,
product_table.price,
inventory_table.barcode
http://sqlfiddle.com/#!9/2f372/37

Group Concat in mysql statement

I've got a table called delitems with some colums.
Within my SELECT statement I want to use a GROUP_CONCAT:
+-------------------------------+-------+--------+--------+-----+
| COLOR | tOTAL | Ptotal | Amount | qty |
+-------------------------------+-------+--------+--------+-----+
| BLUE - W = 55,BLUE - W/O = 93 | 148 | 375 | 55500 | 2 |
+-------------------------------+-------+--------+--------+-----+
mysql>select GROUP_CONCAT(color,' = ',qty) as COLOR, SUM(qTY) AS tOTAL, suM(p_cost) as Ptotal, SUM(qty)*SUM(p_cost) as Amount,count(*) qty from delitems where status='3' Group By cont_no;
Everything works fine except the Amount column. The total amount is wrong! Here the correct value:
+-----------------+-------+--------+--------+-----+
| COLOR | tOTAL | Ptotal | Amount | qty |
+-----------------+-------+--------+--------+-----+
| BLUE - W = 55 | 55 | 125 | 6875 | 1 |
| BLUE - W/O = 93 | 93 | 250 | 23250 | 1 |
+-----------------+-------+--------+--------+-----+
mysql>select GROUP_CONCAT(color,' = ',qty) as COLOR, SUM(qTY) AS tOTAL, suM(p_cost) as Ptotal, SUM(qty)*SUM(p_cost) as Amount,count(*) qty from delitems where status='3' Group By color;
I only want to display it in one line with the correct total amount
Please help.
Should be you need sum(a*b) not sum(a)*sum(b)
select
GROUP_CONCAT(color,' = ',qty) as COLOR
, SUM(qTY) AS tOTAL
, suM(p_cost) as Ptotal
, SUM(qty*(p_cost) as Amount, count(*) qty
from delitems
where status='3' Group By cont_no;

SQL: Combining 2 rows to one from 1 table results in more than one row for subquery

What I have:
One table of fruit food (from which I'm selecting fruit) with two rows for each each fruit, one for small size, one for large size.
id | category | subcategory | title | description | value
-----------------------------------------------------------------
1 | Fruit | Small | Plum | Om, nom, nom! | 0.50
2 | Fruit | Large | Plum | Om, nom, nom! | 1.50
3 | Fruit | Small | Orange | Mmm, citrus. | 0.30
4 | Fruit | Large | Orange | Mmm, citrus. | 0.75
5 | Fruit | Small | Melon | Get in mah belly! | 2.00
6 | Fruit | Large | Melon | Get in mah belly! | 3.10
What I need:
I need to combine the two rows for each fruit into one row:
category, title and description will always be the same for each pair of rows.
id, subcategory and value will always be different for each pair of rows.
id.r1 | id.r2 | category.r1 | title.r1 | description.r1 | subcategory.r1 | value.r1 | subcategory.r2 | value.r2
-----------------------------------------------------------------------------------------------------------------------
1 | 2 | Fruit | Plum | Om, nom, nom! | Small | 0.50 | Large | 1.50
3 | 4 | Fruit | Orange | Mmm, citrus. | Small | 0.30 | Large | 0.75
5 | 6 | Fruit | Melon | Get in mah belly! | Small | 2.00 | Large | 3.10
What I've tried:
SELECT r1.id,
(SELECT r2.id FROM `my_table` r2 WHERE r1.title = r2.title),
r1.category,
r1.subcategory,
(SELECT r2.category FROM `my_table` r2 WHERE r1.title = r2.title)
r1.title,
r1.description,
r1.value,
(SELECT r2.value FROM `my_table` r2 WHERE r1.title = r2.title)
FROM `my_table` r1
WHERE category = "Fruit"
...which produces:
Subquery returns more than 1 row
My question:
How should I modify the above query to achieve what I've described?
You can readily do this with an aggregation:
select category, title, description,
MAX(case when subcategory = 'Small' then id end) as Small_Id,
MAX(case when subcategory = 'Small' then value end) as Small_Value,
MAX(case when subcategory = 'Large' then id end) as Large_Id,
MAX(case when subcategory = 'Large' then value end) as Large_Value
from my_table f
group by category, title, description
Note: This does not include subcategory in the final result because there is no subcategory for the row.
You can also do this as a join, which seems to be the path you were taking:
select fsmall.id, flarge.id, fsmall.category, flarge.category, . . .
from my_table fsmall join
my_table flarge
on fsmall.subcategory = 'small' and flarge.subcategory = 'large' and
fsmall.category = flarge.category and
fsmall.title = flarge.title and
fsmall.description = flarge.description
Depending on whether you might have some missing rows, you might want a left outer join or full outer join.

MySQL: searching children records

Assume 2 tables:
TABLE: team
-----------
| team_id |
===========
| 1 |
-----------
| 2 |
-----------
TABLE: team_member
-------------------------------------------
| team_member_id | team_id | age | gender |
===========================================
| 1 | 1 | 20 | Male |
-------------------------------------------
| 1 | 2 | 25 | Male |
-------------------------------------------
| 1 | 2 | 23 | Female |
-------------------------------------------
How do I search for things like this:
List of all teams that are only male, between ages of 18 and 25.
List of all teams that are male and female, where either gender is between ages of 18 and 25.
Etc.
I'm basically looking for general strategies on how to apply certain filters (e.g. age) across all the children records of team. Suggestions?
team, team_member
You can't just apply a simple WHERE clause if you are checking for only an all male or all female team... it needs to be compared against the full set of team members. Try
select
tm.team_id,
sum( if( tm.gender = 'Male' AND tm.age between 18 and 25, 1, 0 )) as MaleInRange,
count(*) AllTeamMembers
from
team_member tm
group by
tm.Team_ID
having
MaleInRange = AllTeamMembers
Similarly, to ensure you have BOTH male AND female...
select
tm.team_id,
sum( if( tm.age between 18 and 25, 1, 0 )) as AgeInRange,
sum( if( tm.gender = 'Male', 1, 0 )) as MaleCnt,
sum( if( tm.gender = 'Female', 1, 0 )) as FemaleCnt,
count(*) AllTeamMembers
from
team_member tm
group by
tm.Team_ID
having
AgeInRange = AllTeamMembers
AND MaleCnt > 0
AND FemaleCnt > 0
Something like -
SELECT * FROM t1
WHERE key_col > 1
AND key_col < 10;
Check this example - http://www.roseindia.net/sql/mysql-example/mysql-range.shtml. Hope it helps!
You can do it as below:
1. SELECT * FROM T2 WHERE Gender='Male' and Age BETWEEN 18 AND 25.
2. SELECT * FROM T2 WHERE Age BETWEEN 18 AND 25.
Hope it helps!
BTW team_member_id must be unique or this column is useless !!
List of all teams that are male and female, where either gender is between ages of 18 and 25.
SELECT * FROM team_member WHERE Age BETWEEN 18 AND 25 GROUP BY team_id.
result
| team_member_id | team_id | age | gender |
===========================================
| 1 | 1 | 20 | Male |
-------------------------------------------
| 1 | 2 | 25 | Male |
-------------------------------------------