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

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".

Related

MySQL- Count total records based on different values of same column

I have a table as follows
table_user
id name status flag country
====================================================================================================
1 AB 1 0 US
2 BC 1 0 UK
3 CD 0 0 IN
4 DE 3 0 BR
5 EF 3 0 UK
6 FG 2 0 IN
7 GH 4 0 IN
I want to count the no. of records where
status = 1 as totalactiverecords,
status = 0 as totalinactiverecords,
status = 3 as totalrecentactiverecords,
status = 2 as totalemailnotverifiedrecords,
status = 4 as totalemailverifiedrecords,
, and country is UK, all in a single SELECT statement.
Is there any specific way to do it?
I have thought of something like
SELECT COUNT(*) as totalactiverecords WHERE status=1
COUNT(*) as totalinactiverecordsWHERE status=0,
COUNT(*) as totalemailnotverifiedrecords WHERE status=2,
COUNT(*) as totalrecentactiverecords WHERE status=3,
COUNT(*) as totalemailverifiedrecords WHERE status=4
FROM table_user where country=IN
,but that does not seem to work.
You can try this query:
SELECT count(case status when '1' then 1 else null end) as totalactiverecords,
count(case status when '0' then 1 else null end) as totalinactiverecords,
count(case status when '2' then 1 else null end) as totalemailnotverifiedrecords,
count(case status when '3' then 1 else null end) as totalrecentactiverecords,
count(case status when '4' then 1 else null end) as totalemailverifiedrecords
FROM table_user where country='IN'
I usually use CASE WHEN in this kind of problem:
SELECT sum(case when status = 1 then 1 end) as totalactiverecords,
COUNT sum(case when status = 0 then 1 end) as totalinactiverecords,
COUNT sum(case when status = 2 then 1 end) as totalemailnotverifiedrecord,
COUNT sum(case when status = 3 then 1 end) as totalrecentactiverecords,
COUNT sum(case when status = 4 then 1 end) as totalemailverifiedrecords
FROM table_user where country=IN

Slow MySQL queries using SUM()

I have to run two queries in my code to get my tenants balance. However, these queries are too slow.
First query, I get all the tenants and it's unit name:
SELECT t.TenantID
FROM Tenants t
JOIN Units u
ON t.UnitID = u.UnitID
Where t.Prospect = 2
AND t.PropertyID = 8
ORDER
BY CONCAT(Left(Replace(UnitName,'-',''),2),
REPEAT('0', (10-CHAR_LENGTH(UnitName))),
Right(Replace(UnitName,'-',''),
CHAR_LENGTH(Replace(UnitName,'-',''))-2
) )
It returns 500 rows
Then I get the balances in 4 conditions. This query will be inside of first query loop:
Select
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalDebit,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingDebit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalCredit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingCredit
From TenantTransactions
Where TenantID= FirstQuery.TenantID
Am I doing the queries wrong? It's taking like 1 minute to run.
Do this in a single query with GROUP BY.
Try something like this:
SELECT t.TenantID, TotalDebit, HousingDebit, TotalCredit, HousingCredit
FROM Tenants t
JOIN Units u ON t.UnitID = u.UnitID
LEFT JOIN (
Select
TenantID,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalDebit,
SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingDebit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) AS TotalCredit,
SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) AS HousingCredit
From TenantTransactions
Group By TenantID
) sums ON sums.TenantID = t.TenantID
Where t.Prospect = 2
AND t.PropertyID = 8
ORDER
BY CONCAT(Left(Replace(UnitName,'-',''),2),REPEAT('0', (10-CHAR_LENGTH(UnitName))),Right(Replace(UnitName,'-',''),CHAR_LENGTH(Replace(UnitName,'-',''))-2))
The inner query may still run for a while but it will only run once.
Try a compound covering index on TenantTransactions containing these columns: (TenantID, TransactionTypeID, ChargeTypeID, TransactionAmount) to optimize the query with the SUMs in it.
Try a compound index on Tenants with the columns (PropertyID, Prospect) in it.
Here's another way to do it with a subquery. You know, the performance problem might not be database performance, but the back and forth between your database and application server. So that is where a single query will help.
SELECT t.TenantID,
(SELECT SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS TotalDebit,
(SELECT SUM(CASE WHEN TransactionTypeID = 1 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS HousingDebit,
(SELECT SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID != 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS TotalCredit,
(SELECT SUM(CASE WHEN TransactionTypeID = 2 AND ChargeTypeID = 6 THEN TransactionAmount ELSE 0 END) From TenantTransactions TT WHERE TT.TenantID=t.TenantID) AS HousingCredit
FROM Tenants t
JOIN Units u
ON t.UnitID = u.UnitID
Where t.Prospect = 2
AND t.PropertyID = 8
ORDER
BY CONCAT(Left(Replace(UnitName,'-',''),2),REPEAT('0', (10-CHAR_LENGTH(UnitName))),Right(Replace(UnitName,'-',''),CHAR_LENGTH(Replace(UnitName,'-',''))-2))

Need help in Merging Two query for HP ALM

I have two different query in HP ALM, but i want to merge and get it into one. I am not that good in SQL query so I am facing hard time in merging the query.
Query 1: Getting the execution Count for the tester
Select
TESTCYCL.TC_ACTUAL_TESTER as 'Tester',
sum(case when TC_Status In('Blocked','Passed','Failed','Not Completed') then 1 else 0 end) as 'Total',
sum(case when TC_Status = 'Passed' then 1 else 0 end) as 'Pass',
sum(case when TC_Status = 'Failed' then 1 else 0 end) as 'Fail',
sum(case when TC_Status = 'Blocked' then 1 else 0 end) as 'Blocked',
sum(case when TC_Status In('Not Completed','Defferred','N/A') then 1 else 0 end) as 'Others'
From TESTCYCL
Where
TESTCYCL.TC_EXEC_DATE = CAST(CURRENT_TIMESTAMP AS DATE)
And
TESTCYCL.TC_ACTUAL_TESTER in ('Username1')
Group by TC_ACTUAL_TESTER
Query 2: Getting the Defect raise by the tester
SELECT
BG_DETECTED_BY,
Sum(case when BG_Status Not in ('Closed','Defect Resolved','Rejected')then 1 else 0 end) as 'Defect Raised'
FROM BUG
Where BUG.BG_DETECTED_BY in ('username1')
AND BUG.BG_DETECTION_DATE = CAST(CURRENT_TIMESTAMP AS DATE)
Group by BG_DETECTED_BY
I have tried inner join/ Left Join but the count of the defect raised by the user is not matching
Query3 : That i have tried:
Select
TESTCYCL.TC_ACTUAL_TESTER as 'Tester',
sum(case when TC_Status In('Blocked','Passed','Failed','Not Completed') then 1 else 0 end) as 'Total',
sum(case when TC_Status = 'Passed' then 1 else 0 end) as 'Pass',
sum(case when TC_Status = 'Failed' then 1 else 0 end) as 'Fail',
sum(case when TC_Status = 'Blocked' then 1 else 0 end) as 'Blocked',
sum(case when TC_Status In('Not Completed','Defferred','N/A') then 1 else 0 end) as 'Others',
Sum(case when BG_Status Not in ('Closed','Defect Resolved','Rejected')then 1 else 0 end) as 'Defect Raised'
From TESTCYCL
Left Join BUG
on TESTCYCL.TC_ACTUAL_TESTER = BUG.BG_DETECTED_BY
AND BUG.BG_DETECTION_DATE = CAST(CURRENT_TIMESTAMP AS DATE)
Where TESTCYCL.TC_EXEC_DATE = CAST(CURRENT_TIMESTAMP AS DATE)
And TESTCYCL.TC_ACTUAL_TESTER in ('username1')
Group by TC_ACTUAL_TESTER
Out is mentioned as below:
Expected Output:
Tester Total Execution Passed Failed ... Defect Raised
A 5 3 2 10
Actual Output:
Tester Total Execution Passed Failed ... Defect Raised
A 56 3 2 45
The problem is you are doing the COUNT() over the product cartesian. instead of concatenating the result.
Right now you are doing
COUNT(A*B) instead of COUNT(A) || COUNT(B)
general example, if you have two queries
SELECT * FROM A (ex: 10 rows)
SELECT * FROM B (ex: 10 rows)
What you need is:
SELECT temp1.*, temp2.*
FROM (SELECT * FROM A) as temp1
JOIN (SELECT * FROM B) as temp2
ON temp1.ID = temp2.ID

MySQL using Sum and Case

I'm trying to create a GridView with ASP.NET connecting to a MySQL database. The data appears like below.
BusinessUnit OrderDate Canceled
UnitA 1/15/2013 N
UnitA 10/1/2013 N
UnitB 10/15/2013 N
UnitB 10/22/2013 N
UnitB 10/22/2013 N
Based on the records above, I'd like the result to appear like below
BusinessUnit TodaysOrders ThisMonthsOrders ThisYearsOrders
UnitA 0 1 2
UnitB 2 3 3
My current code is below. It's giving me error (something about DatabaseName.sum does not exist. Check the
Function Name Parsing and Resolution' section... )
Select
SUM (CASE WHEN (OrderDate)=DATE(NOW()) THEN 1 ELSE 0 END) AS TodaysOrders,
SUM (CASE WHEN YEAR(OrderDate) = YEAR(CURDATE()) AND MONTH(OrderDate) = MONTH(CURDATE()) THEN 1 ELSE 0 END) AS ThisMonthsOrders,
SUM (CASE WHEN YEAR(main_order_managers.creation_date) = YEAR(CURDATE()) THEN 1 ELSE 0 END) AS ThisYearsOrders
code continues
FROM OrderTable WHERE OrderTable.Canceled. <> 'Y';
Is Sum Case the best use here?
The error is caused by the space between function name and parenthesis
SUM (CASE WHEN ...
^^
Read more Function Name Parsing and Resolution
Try
SELECT BusinessUnit,
SUM(CASE WHEN OrderDate = CURDATE() THEN 1 ELSE 0 END) TodaysOrders,
SUM(CASE WHEN DATE_FORMAT(OrderDate, '%Y%m') = DATE_FORMAT(CURDATE(), '%Y%m') THEN 1 ELSE 0 END) ThisMonthsOrders,
SUM(CASE WHEN YEAR(OrderDate) = YEAR(CURDATE()) THEN 1 ELSE 0 END) ThisYearsOrders
FROM OrderTable
WHERE Canceled <> 'Y'
GROUP BY BusinessUnit
Here is SQLFiddle demo

MySQL optimize multiple subquery into nested inner join?

I have 3 tables; contracts, dealers, and users.
users have many dealers and dealers have many contracts but the contracts are not directly associated with the users.
I am trying to build a report that gets me a monthly count of completed contracts grouped by user for the last 12 months.
So far I have built a multiple subquery, which is very slow: SQL Fiddle
SELECT *,
( SELECT count(*) FROM contracts
WHERE
dealer_id IN
( SELECT id FROM dealers WHERE user_id = User.id )
AND status = 'Paid'
AND completion_date BETWEEN
'2012-08-01 00:00:00' AND '2012-08-31 23:59:59'
) AS Aug_2012,
( SELECT count(*) FROM contracts
WHERE
dealer_id IN
( SELECT id FROM dealers WHERE user_id = User.id )
AND status = 'Paid'
AND completion_date BETWEEN
'2012-09-01 00:00:00' AND '2012-09-30 23:59:59'
) AS Sep_2012
FROM users AS User
WHERE
id IN( SELECT user_id FROM dealers WHERE active = 1 AND user_id IS NOT NULL GROUP BY user_id )
AND id != 1
ORDER BY User.name ASC
Instead of the subquery which selects each month I'd like to use something like this:
COUNT(*) as last_12_months,
SUM(case when MONTH(completion_date) = 8 then 1 else 0 end) as Aug_2012,
SUM(case when MONTH(completion_date) = 9 then 1 else 0 end) as Sep_2012,
etc.
Since I'd be returning multiple columns I would have to restructure it, but I'm not sure how. If I use an INNER JOIN what clause do I join on?
Here's the final query based on Mikhail's answer below:
SELECT
User.*,
SUM(case when MONTH(completion_date) = 8 then 1 else 0 end) AS Aug_2012,
SUM(case when MONTH(completion_date) = 9 then 1 else 0 end) AS Sep_2012,
SUM(case when MONTH(completion_date) = 10 then 1 else 0 end) AS Oct_2012,
SUM(case when MONTH(completion_date) = 11 then 1 else 0 end) AS Nov_2012,
SUM(case when MONTH(completion_date) = 12 then 1 else 0 end) AS Dec_2012,
SUM(case when MONTH(completion_date) = 1 then 1 else 0 end) AS Jan_2013,
SUM(case when MONTH(completion_date) = 2 then 1 else 0 end) AS Feb_2013,
SUM(case when MONTH(completion_date) = 3 then 1 else 0 end) AS Mar_2013,
SUM(case when MONTH(completion_date) = 4 then 1 else 0 end) AS Apr_2013,
SUM(case when MONTH(completion_date) = 5 then 1 else 0 end) AS May_2013,
SUM(case when MONTH(completion_date) = 6 then 1 else 0 end) AS Jun_2013,
SUM(case when MONTH(completion_date) = 7 then 1 else 0 end) AS Jul_2013,
SUM(case when completion_date BETWEEN '2012-08-01 00:00:00' AND '2013-07-31 23:59:59' then 1 else 0 end) as last_12_months
FROM users AS User
LEFT OUTER JOIN
(
SELECT id, user_id FROM dealers
WHERE active = 1 AND user_id IS NOT NULL
) AS Dealer ON User.id = Dealer.user_id
LEFT OUTER JOIN
(
SELECT completion_date, status, dealer_id FROM contracts
WHERE completion_date BETWEEN '2012-08-01 00:00:00' AND '2013-07-31 23:59:59' AND status = 'Paid' AND cancelled = 0
) AS Contract on Dealer.id = Contract.dealer_id
WHERE
User.id IN
(
SELECT user_id FROM dealers
WHERE active = 1 AND user_id IS NOT NULL
GROUP BY user_id
)
GROUP BY
User.id order by User.name asc
This is about 4 times faster.
Try this:
select
User.id, User.name,
sum(case when MONTH(completion_date) = 8 and Year(completion_date)=2012 then 1 else 0 end) as Aug_2012,
sum(case when MONTH(completion_date) = 9 and Year(completion_date)=2012 then 1 else 0 end) as Sep_2012,
sum(case when MONTH(completion_date) = 10 and Year(completion_date)=2012 then 1 else 0 end) as Oct_2012,
sum(case when MONTH(completion_date) = 11 and Year(completion_date)=2012 then 1 else 0 end) as Nov_2012,
sum(case when MONTH(completion_date) = 12 and Year(completion_date)=2012 then 1 else 0 end) as Dec_2012,
sum(case when MONTH(completion_date) = 1 and Year(completion_date)=2013 then 1 else 0 end) as Jan_2012,
sum(case when MONTH(completion_date) = 2 and Year(completion_date)=2013 then 1 else 0 end) as Feb_2012,
sum(case when MONTH(completion_date) = 3 and Year(completion_date)=2013 then 1 else 0 end) as Mar_2012,
sum(case when MONTH(completion_date) = 4 and Year(completion_date)=2013 then 1 else 0 end) as Apr_2012,
sum(case when MONTH(completion_date) = 5 and Year(completion_date)=2013 then 1 else 0 end) as May_2012,
sum(case when MONTH(completion_date) = 6 and Year(completion_date)=2013 then 1 else 0 end) as Jun_2012,
sum(case when MONTH(completion_date) = 7 and Year(completion_date)=2013 then 1 else 0 end) as Jul_2012
from users AS User
left outer join dealers on
User.id=dealers.user_id
left outer join contracts on
dealers.id=contracts.dealer_id
group by
User.id,
contracts.status
having
contracts.status='Paid'
order by
User.name asc;