How to group row values based on same column name - mysql

I have created the schema and query on SQL Fiddle:
SQL Fiddle(http://sqlfiddle.com/#!9/e43a13/1)
I am trying to get prices of work type according to the urgency and academic level, I am successful in getting that but I can't figure out how to format it in this way:
| Urgency | Academic Level Name 1 | Academic Level 2 | Academic Level 3 |
-------------------------------------------------------------------------------------------
| 1 hour |Price Of Academic Level 1|Price Of Academic Level 2 | Price Of Academic Level 3|
-------------------------------------------------------------------------------------------
I have as the output:

If you are trying to group by urgency, you may consider below query.
SELECT
utt.UrgencyTime as `Urgency`
, sum(case when al.AcademicID = 1 then wtd.Price else 0 end) as `Academic Level Name 1`
, sum(case when al.AcademicID = 2 then wtd.Price else 0 end) as `Academic Level Name 2`
, sum(case when al.AcademicID >= 3 then wtd.Price else 0 end) as `Academic Level Name 3`
FROM `WorkTypeData` wtd
JOIN UrgencyTimeTable utt ON utt.UrgencyID = wtd.UrgencyID
JOIN WorkType wt ON wt.WorkTypeID = wtd.WorkTypeID
JOIN AcademicLevel al ON al.AcademicID = wtd.AcademicLevelID
WHERE wt.WorkTypeID = '1'
GROUP BY utt.UrgencyTime

to get prices of work type according to the urgency and academic level, use the following query,
SELECT
utt.UrgencyTime as Urgency,
al.LevelName as "Academic Level Name",
wtd.Price
FROM `WorkTypeData` wtd
JOIN
UrgencyTimeTable utt
ON
utt.UrgencyID = wtd.UrgencyID
JOIN
WorkType wt
ON
wt.WorkTypeID = wtd.WorkTypeID
JOIN
AcademicLevel al
ON
al.AcademicID = wtd.AcademicLevelID
WHERE wt.WorkTypeID = '1'
group by utt.UrgencyTime, al.LevelName

I Think this might be helpful
SELECT
utt.UrgencyTime AS `Urgency` ,
CASE
WHEN al.AcademicID = 1 THEN wtd.Price
ELSE 0
END AS `Academic LEVEL Name 1` ,
CASE
WHEN al.AcademicID = 2 THEN wtd.Price
ELSE 0
END AS `Academic LEVEL Name 2` ,
CASE
WHEN al.AcademicID = 7 THEN wtd.Price
ELSE 0
END AS `Academic LEVEL Name 7` ,
CASE
WHEN al.AcademicID = 8 THEN wtd.Price
ELSE 0
END AS `Academic LEVEL Name 8` ,
CASE
WHEN al.AcademicID = 9 THEN wtd.Price
ELSE 0
END AS `Academic LEVEL Name 9`
FROM
`WorkTypeData` wtd
JOIN UrgencyTimeTable utt ON utt.UrgencyID = wtd.UrgencyID
JOIN WorkType wt ON wt.WorkTypeID = wtd.WorkTypeID
JOIN AcademicLevel al ON al.AcademicID = wtd.AcademicLevelID
group BY utt.UrgencyTime, al.AcademicID

Related

Getting distinct values from table

Im having and issue where in my table FarmerGroups I have multiple records by BSI_Code and I am getting double results for GallonsIssued due to this inner join. Is there a way to get the unique value of GallonsIssued or a way to just get results by individual BSI_CODE
With Summary as (
Select B_NAME as Branch, LOC as Location
,SUM(payment) as Gallons
,SUM(case when printed = 1 THEN Fee ELSE NULL END) as FeeCollected
,SUM(case when printed = 0 THEN Fee ELSE NULL END) as FeeNotCollected
,SUM(case when printed = 1 THEN Payment ELSE NULL END) as GallonsIssued
,SUM(case when printed = 0 THEN Payment ELSE NULL END) as GallonsNotIssued
From SicbWeeklyDeliveriesFuel F Inner Join FarmerGroups G ON G.BSI_CODE = F.BSI_CODE AND G.CROP_SEASON = F.CROP_SEASON AND F.B_NAME = G.BRANCH
Where F.CROP_SEASON = #cropseason
Group By B_NAME, LOC
)
SELECT Branch
,Location
,Gallons
,GallonsIssued
,GallonsNotIssued
,FeeCollected
,FeeNotCollected
,((GallonsIssued/Gallons) * 100) as pct_GallonsCollected
FROM Summary
Order by Location, Branch
For SicbWeeklyDeliveriesFuel
BSI_CODE
Payment
LOC
CROP_SEASON
Fee
B_NAME
FNAME
66
125
CZ
5
12.5
DOUGLAS
John K
55
147
OW
5
14.7
CALEDONIA
Tim H
66
95
CZ
5
9.5
DOUGLAS
John K
For Farmer Groups
BSI_CODE
Farmer
CROP_SEASON
BRANCH
TEST_GROUP
66
John K
5
DOUGLAS
1A
55
Tim H
5
CALEDONIA
1B
66
John K
5
DOUGLAS
2A
Your selection for the JOIN of G.BSI_CODE = F.BSI_CODE AND G.CROP_SEASON = F.CROP_SEASON AND F.B_NAME = G.BRANCH does not uniquely define the rows.
You will need to also include F..FNAME = G.Farmer otherwise the first row of SicbWeeklyDeliveriesFuel (BSI_CODE = 66, CROP_SEASON = 5 and B_NAME = DOUGLAS) matches both the first and last rows of FarmerGroups. Likewise the third row also matches the same two rows in FarmerGroups.
The reason for the duplication is the field TEST_GROUP in FarmerGroups Table.
But you don't need this field in the Join.
First,a CTE to get the info you need in the join without duplicates.
then your old join to the new CTE.
Try this:
WITH FarmersGroup AS
(
SELECT DISTINCT
BSI_CODE
, CROP_SEASON
, BRANCH
FROM FarmerGroups
)
, Summary AS
(
SELECT
Branch = B_NAME
, Location = LOC
, Gallons = SUM(payment)
, FeeCollected = SUM(case when printed = 1 THEN Fee ELSE NULL END)
, FeeNotCollected = SUM(case when printed = 0 THEN Fee ELSE NULL END)
, GallonsIssued = SUM(case when printed = 1 THEN Payment ELSE NULL END)
, GallonsNotIssued = SUM(case when printed = 0 THEN Payment ELSE NULL END)
FROM SicbWeeklyDeliveriesFuel F
JOIN FarmerGroup G ON G.BSI_CODE = F.BSI_CODE
AND G.CROP_SEASON = F.CROP_SEASON
AND G.BRANCH = F.B_NAME
WHERE F.CROP_SEASON = #cropseason
GROUP BY
B_NAME, LOC
)
SELECT
Branch
, Location
, Gallons
, GallonsIssued
, GallonsNotIssued
, FeeCollected
, FeeNotCollected
, pct_GallonsCollected = ((GallonsIssued/Gallons) * 100)
FROM Summary
ORDER BY
Location
, Branch
You can use Andy's code above and it should do the job or you can just replace the table join in your current query
Change the following
Inner Join FarmerGroups G ON G.BSI_CODE = F.BSI_CODE AND G.CROP_SEASON = F.CROP_SEASON AND F.B_NAME = G.BRANCH
to
Inner join (select SELECT DISTINCT
BSI_CODE
, CROP_SEASON
, BRANCH
FROM FarmerGroups ) G on
ON G.BSI_CODE = F.BSI_CODE AND G.CROP_SEASON = F.CROP_SEASON AND F.B_NAME = G.BRANCH

Sum of group by using mysql

I am having three tables financial_year, house_details, consumer_details. I need to get the sum of each tax group by year and subincome. My table and query is in this link: sqlfiddle
Getting Result:
Name house_number address subincome financial_year gtax htax LTAX
--------------------------------------------------------------------------
Bala 22 Mumbai Garbage tax 2015-2016 200 NULL NULL
Bala 22 Mumbai Garbage tax 2016-2017 250 NULL NULL
Bala 22 Mumbai House tax 2015-2016 NULL 0 NULL
Bala 22 Mumbai House tax 2016-2017 NULL 145 NULL
Bala 22 Mumbai Light tax 2015-2016 NULL NULL 510
Bala 22 Mumbai Light tax 2016-2017 NULL NULL 200
Expecting Result:
Name house_number address gtax htax LTAX
--------------------------------------------------------
Bala 22 Mumbai 450 145 710
You are looking for conditional aggregation note this solution only works if there is an entry for each subincome(tax type)in house details for each financial year.
SELECT c.consumer_name as Name, c.house_number, c.address,
sum(CASE WHEN h.subincome = 'Garbage tax' THEN f.garbage_tax else 0 end) -
sum(CASE WHEN h.subincome = 'Garbage tax' THEN h.rupees else 0 END) as gtax,
sum(CASE WHEN h.subincome = 'House tax' THEN f.house_tax else 0 end) -
sum(CASE WHEN h.subincome = 'House tax' THEN h.rupees else 0 END) as htax,
sum(CASE WHEN h.subincome = 'Light tax' THEN f.light_tax else 0 end) -
sum(CASE WHEN h.subincome = 'Light tax' THEN h.rupees else 0 END) as LTAX
from house_details h
INNER JOIN financial_year f ON h.financial_year = f.year AND h.house_id = f.house_number
INNER JOIN consumer_details c ON h.house_id = c.house_number AND h.financial_year != '2017-2018'
group by c.consumer_name , c.house_number, c.address
result
+------+--------------+---------+------+------+------+
| Name | house_number | address | gtax | htax | LTAX |
+------+--------------+---------+------+------+------+
| Bala | 22 | Mumbai | 450 | 145 | 710 |
+------+--------------+---------+------+------+------+
1 row in set (0.03 sec)
If it is not guaranteed that there will be an entry for every subincome in every financial year then the the solution has to be driven from the tax due table (financial year) which in my view is badly designed ,inflexible and forces a sub optimal solution
select c.consumer_name as Name, s.house_number, c.address,
sum(case when subincome = 'garbage tax' then taxdue else 0 end) - sum(case when subincome = 'garbage tax' then taxpaid else 0 end) as gtax,
sum(case when subincome = 'house tax' then taxdue else 0 end) - sum(case when subincome = 'house tax' then taxpaid else 0 end) as htax,
sum(case when subincome = 'light tax' then taxdue else 0 end) - sum(case when subincome = 'light tax' then taxpaid else 0 end) as ltax
from
(
SELECT F.`house_number`, F.`year`, F.`house_tax` taxdue, F.`createdAt`, F.`updatedAt`,ifnull(h.subincome,'house_tax') subincome,ifnull(H.RUPEES,0) taxpaid
FROM FINANCIAL_YEARS F
LEFT JOIN house_details H ON H.HOUSE_ID = F.HOUSE_NUMBER AND H.SUBINCOME = 'house tax' and f.year = h.financial_year
#where f.house_number = 22
union all
SELECT F.`house_number`, F.`year`, F.`light_tax`, F.`createdAt`, F.`updatedAt`,ifnull(h.subincome,'light tax'),ifnull(H.RUPEES,0)
FROM FINANCIAL_YEARS F
LEFT JOIN house_details H ON H.HOUSE_ID = F.HOUSE_NUMBER AND H.SUBINCOME = 'light tax' and f.year = h.financial_year
#where f.house_number = 2
union all
SELECT F.`house_number`, F.`year`, F.`garbage_tax`, F.`createdAt`, F.`updatedAt`,ifnull(h.subincome,'garbage tax'),ifnull(H.RUPEES,0)
FROM FINANCIAL_YEARS F
LEFT JOIN house_details H ON H.HOUSE_ID = F.HOUSE_NUMBER AND H.SUBINCOME = 'garbage tax' and f.year = h.financial_year
#where f.house_number = 2
) s
join consumer_details c on s.house_number = c.house_number
where s.year <> '2017-2018'
group by c.consumer_name , s.house_number, c.address
Try this it will give exact result which you want, I just create a drive table and then sum
SELECT name
, house_number
, address
, SUM(gtax) as gtax
, SUM(htax) as htax
, SUM(LTAX) LTAX
FROM (SELECT c.consumer_name as Name
, c.house_number
, c.address,h.subincome
, h.financial_year
, CASE WHEN h.subincome = 'Garbage tax' THEN f.garbage_tax - sum(h.rupees)END as gtax
, CASE WHEN h.subincome = 'House tax' THEN f.house_tax - sum(h.rupees) END as htax
, CASE WHEN h.subincome = 'Light tax' THEN f.light_tax - sum(h.rupees) END as LTAX
FROM house_details h
INNER JOIN financial_year f ON h.financial_year = f.year AND h.house_id = f.house_number
INNER JOIN consumer_details c ON h.house_id = c.house_number AND h.financial_year != '2017-2018'
GROUP BY h.subincome, h.financial_year) as main
GROUP BY house_number
then result is :

Appending data from different tables - mysql

I have the following tables Job description and Candidate.
Each job description can be related to n candidates. The candidates are obtained from different sources(a, b, c d) - candidate.source.
I want a single query to list me the JD ids, with count of candidates for each source for each JD, as shown below:
JD id | candidate name | count of candidates - source a | count of candidates - source b | count of candidates - source | c..............
Try using the query as a template:
select
JobDescriptionName,
SUM(ACount) CountOfCandidatesOfA ,
SUM(BCount) CountOfCandidatesOfB,
SUM(CCount) CountOfCandidatesOfC ,
SUM(DCount) CountOfCandidatesOfD
from
( select JobDescriptionID, (CASE WHEN Source = 'a' THEN 1 ELSE 0 END) AS ACount,
(CASE WHEN Source = 'b' THEN 1 ELSE 0 END) AS BCount,
(CASE WHEN Source = 'c' THEN 1 ELSE 0 END) AS CCount,
(CASE WHEN Source = 'd' THEN 1 ELSE 0 END) AS DCount
from Candidate) AS DerivedCandidate
inner join JobDescription ON JobDescription.JobDescriptionID = DerivedCandidate.JobDescriptionID group by JobDescriptionID;
I know there is already an accepted answer but in the effort of learning myself more about SQL here is an alternative way applying the case directly in the initial select without the sub-select:
Select
jd.id,
jd.name,
sum(case when c.source = 'a' then 1 else 0 end) as sourceA,
sum(case when c.source = 'b' then 1 else 0 end) as sourceB,
sum(case when c.source = 'c' then 1 else 0 end) as sourceC,
sum(case when c.source = 'd' then 1 else 0 end) as sourceD
from JobDescription as jd
join Candidate as c on c.jobId = jd.id
group by jd.id, jd.name
SQL Fiddle Demo
SELECT JD id, COUNT(Candidate), source
FROM table1
GROUP BY JD id,source

SQL count specific value over multiple columns and rows

I feel as if this should be quite easy, but can't seem to find a solution.
Suppose I have the following table:
|--------||---||---||---||---||---||---||---|
|Company ||q1 ||q2 ||q3 ||q4 ||q5 ||q6 ||q7 |
|--------||---||---||---||---||---||---||---|
|abc ||1 ||2 ||1 ||3 ||2 ||2 ||1 |
|abc ||2 ||2 ||1 ||2 ||3 ||1 ||1 |
|abc ||1 ||1 ||3 ||3 ||1 ||2 ||2 |
|abc ||1 ||2 ||1 ||3 ||0 ||1 ||3 |
I want to count the number of times '1' appears in the table, so the query should, in this case, result with 12. I tried 'hardcoding' it, like the following query. But that just results in the rows containing a 1, so in this case 4. How do I count the number of times '1' occurs, thus resulting in a count of 12?
SELECT COUNT(*)
FROM table
WHERE Company = 'abc'
AND (
q1 = '1'
OR q2 = '1'
OR q3 = '1'
OR q4 = '1'
OR q5 = '1'
OR q6 = '1'
OR q7 = '1'
)
SELECT SUM(
IF(q1 = 1, 1, 0) +
IF(q2 = 1, 1, 0) +
IF(q3 = 1, 1, 0) +
IF(q4 = 1, 1, 0) +
IF(q5 = 1, 1, 0) +
IF(q6 = 1, 1, 0) +
IF(q7 = 1, 1, 0)
)
FROM table
WHERE Company = 'abc'
This is very weird assignment but:
http://sqlfiddle.com/#!9/2e7aa/3
SELECT SUM((q1='1')+(q2='1')+(q3='1')+(q4='1')+(q5='1')+(q6='1')+(q7='1'))
FROM table
WHERE Company = 'abc'
AND '1' IN (q1,q2,q3,q4,q5,q6,q7)
Not so easy, each column needs to be hard-coded. I'd try something using a CASE or DECODE.
SELECT
SUM(
CASE WHEN q1 = 1 THEN 1 ELSE 0 END +
CASE WHEN q2 = 1 THEN 1 ELSE 0 END +
CASE WHEN q3 = 1 THEN 1 ELSE 0 END +
CASE WHEN q4 = 1 THEN 1 ELSE 0 END +
CASE WHEN q5 = 1 THEN 1 ELSE 0 END +
CASE WHEN q6 = 1 THEN 1 ELSE 0 END +
CASE WHEN q7 = 1 THEN 1 ELSE 0 END)
FROM table
WHERE Company = 'abc'
Using a SUM instead of a COUNT will allow the CASE statement to be SUMed.
Use conditional COUNT
SELECT COUNT(case when q1 = '1' then 1 end) +
COUNT(case when q2 = '1' then 1 end) +
COUNT(case when q3 = '1' then 1 end) +
COUNT(case when q4 = '1' then 1 end) +
COUNT(case when q5 = '1' then 1 end) +
COUNT(case when q6 = '1' then 1 end) +
COUNT(case when q7 = '1' then 1 end) as ones_total
FROM table
WHERE Company = 'abc'
For reasons of efficiency I don't recommend actually using this approach; but for learning purposes here's another way you could have broken down the problem along the lines of the way you were thinking about it.
select sum(c) as total_ones
from
(
select count(*) c from table where q1 = 1 union all
select count(*) from table where q2 = 1 union all
select count(*) from table where q3 = 1 union all
select count(*) from table where q4 = 1 union all
select count(*) from table where q5 = 1 union all
select count(*) from table where q6 = 1 union all
select count(*) from table where q7 = 1
) t

how to select and group mysql data based on the following table

how can I achieve the desired result in mysql if my table looks like this.
result|year
1 |2011
2 |2011
1 |2011
0 |2011
1 |2012
2 |2012
1 = Won, 2 = lost, 0 = draw
Every year can have multiple values like this. Not sure how I can get the desired result like below.
year won lost draw totalPlayed
2011 2 1 1 3
2012 1 1 0 2
I have tried the following query but does not get the desired result
select year,
league_types.league_name,
sum(if(result = 1,1,0)) as won,
sum(if(result = 0,1,0)) as draw,
sum(if(result = 4,1,0)) as noResult,
sum(if(result = 2,1,0)) as lost,
sum(if(result = 3,1,0)) as tied,
sum(if(result > 0 and result < 4,1,0)) as played
from match_score_card
inner join fixtures on match_score_card.match_id = fixtures.match_id
inner join league_types on fixtures.league_id = league_types.league_id
where
team_id = 1 group by year order by year desc
Here is the SQL Fiddle that demonstrates the following query:
SELECT m.year,
SUM(CASE WHEN m.result = 1 THEN 1 ELSE 0 END) AS 'Won',
SUM(CASE WHEN m.result = 2 THEN 1 ELSE 0 END) AS 'Lost',
SUM(CASE WHEN m.result = 0 THEN 1 ELSE 0 END) AS 'Draw',
COUNT(*) AS 'TotalPlayed'
FROM MyTable AS m
GROUP BY m.year
I'm not familiar with that IF function in mySQL, but this standard SQL should work:
select year
, league_types.league_name
, sum(CASE WHEN result = 1 THEN 1 ELSE 0 END) as won
, sum(CASE WHEN result = 2 THEN 1 ELSE 0 END) as lost
, sum(CASE WHEN result = 3 THEN 1 ELSE 0 END) as draw
, sum(CASE WHEN result = 4 THEN 1 ELSE 0 END) as noResult
, sum(CASE WHEN result = 1
or result = 2 THEN 1 ELSE 0 END) as played
from match_score_card
inner join fixtures
on match_score_card.match_id = fixtures.match_id
inner join league_types
on fixtures.league_id = league_types.league_id
where team_id = 1
group by year, league_types.league_name
order by year desc, league_types.league_name
I'm guessing that you only want to count wins and losses as "played".