SQL query - How to exclude WHERE for specific field - mysql

See the SQL query below, it work fine. It calculate the number of Yes, NOT, Other and the number of matching mobile number [Sales field] (D.MobileNo = S.mobile)
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'Not' THEN 1 ELSE 0 END) as Not,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S on D.MobileNo = S.mobile
WHERE source = 'Network'
AND UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
GROUP BY D.Username
ORDER BY TOTAL DESC
I want to exclude WHERE for the Sales field - it should not be part from CheckDate. Meaning it should check any record in the dairy table without CheckDate for the Sales field.
How can that be done?

If you really want those results in only one query, this might do the trick.
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'Not' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) as Not,
SUM(CASE WHEN D.type = '' AND UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL,
SUM(CASE WHEN UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 THEN 1 ELSE 0 END) AS TOTALINCHECKDATE
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S on D.MobileNo = S.mobile
WHERE source = 'Network'
GROUP BY D.Username
ORDER BY TOTAL DESC
Note that "TOTAL" will count all rows (including those who where not within your CheckDate range), TOTALINCHECKDATE return the same value as in your previous query.
Obviously, this can still be optimized.

Assuming username exists also in SALES table
SELECT Username,SUM(Yes) As Yes, SUM(`Not`) As `Not`
, SUM(Other) As Other, SUM(sales) Sales, SUM(total)
FROM (
-- get diary data
SELECT username,mobileNo As mobile,
CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END as Yes,
CASE WHEN D.type = 'Not' THEN 1 ELSE 0 END as `Not`,
CASE WHEN D.type = '' THEN 1 ELSE 0 END as Other,
0 As sales, 1 as total
FROM dairy as D
WHERE source = 'Network'
AND UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
UNION ALL
-- get all sales
SELECT DISTINCT username,mobile, 0 as Yes, 0 as `Not`, 0 As Other, 1 As sales, 0 As total
FROM sales
WHERE UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
) AS a
GROUP BY Username
Also try your original query with date addition
SELECT D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'Not' THEN 1 ELSE 0 END) as Not,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales WHERE UNIX_TIMESTAMP(CheckDate) >= 1309474800 AND UNIX_TIMESTAMP(CheckDate) <= 1311894000 ) as S on D.MobileNo = S.mobile
WHERE source = 'Network'
AND UNIX_TIMESTAMP(CheckDate) >= 1309474800
AND UNIX_TIMESTAMP(CheckDate) <= 1311894000
GROUP BY D.Username
ORDER BY TOTAL DESC

Related

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))

SSRS calculate % of desired colums in column group in matrix

SELECT PatchPhase.PhaseName, MAX(PatchPhase.Sequence) AS seq,
PatchState.Application, PatchState.Objectname, PatchState.Jobname,
PatchState.Streamname, COUNT(*) AS Total,
PatchState.Jobdescription,
PatchState.Status, PatchState.Timestamp
FROM PatchState
INNER JOIN PatchPhase ON PatchState.Phase = PatchPhase.PhaseTech
WHERE (PatchPhase.PhaseName IN (#Phase))
AND (PatchState.Application IN (#Application)) AND (PatchState.Timestamp >= #StartDate)
AND (PatchState.Timestamp <= #EndDate)
GROUP BY PatchPhase.PhaseName, PatchState.Application, PatchState.Objectname,
PatchState.Jobname, PatchState.Streamname, PatchState.Jobdescription, PatchState.Status,
PatchState.Timestamp
ORDER BY PatchState.Application
I am working on matrix and I have column group of status which contains 3 columns (planned, running,completed). I want to sum planned+completed and divide by total column.
Total column is outside the column group.
I do find some answers but I did not get how should I use in my code
can someone please help?
Try using this to aggregate, and then use a table instead of a matrix. You will not need a column group now. As I cannot run the sql I can't promise it is perfect but perhaps you could have a little play with it if not. It should offer a guide if nothing else.
SELECT
PatchPhase.PhaseName,
MAX(PatchPhase.Sequence) AS seq,
PatchState.Application,
PatchState.Objectname,
PatchState.Jobname,
PatchState.Streamname,
PatchState.Jobdescription,
SUM(case when PatchState.Status = 'Planned' then 1 else 0 end) as 'Planned',
SUM(case when PatchState.Status = 'Running' then 1 else 0 end) as 'Running',
SUM(case when PatchState.Status = 'Completed' then 1 else 0 end) as 'Completed',
(SUM(case when PatchState.Status = 'Planned' then 1 else 0 end) + SUM(case when PatchState.Status = 'Running' then 1 else 0 end)) /
(SUM(case when PatchState.Status = 'Planned' then 1 else 0 end) + SUM(case when PatchState.Status = 'Running' then 1 else 0 end) + SUM(case when PatchState.Status = 'Completed' then 1 else 0 end)) as totalPercentage
PatchState.Timestamp
FROM
PatchState
INNER JOIN PatchPhase
ON PatchState.Phase = PatchPhase.PhaseTech
WHERE
(PatchPhase.PhaseName IN (#Phase))
AND (PatchState.Application IN (#Application))
AND (PatchState.Timestamp >= #StartDate)
AND (PatchState.Timestamp <= #EndDate)
GROUP BY
PatchPhase.PhaseName,
PatchState.Application,
PatchState.Objectname,
PatchState.Jobname,
PatchState.Streamname,
PatchState.Jobdescription,
PatchState.Status,
PatchState.Timestamp
ORDER BY
PatchState.Application
You can get a value displayed in a text box from expression =Reportitems!Textbox133.Value
instead of textbox133 in the above expression you have to give the textbox name of the textbox from which you want the value. In your case the total column

mySQL Sum in the sum column

SELECT tbl_trans.trans_username,
Sum(Case When tbl_trans.trans_type <> 'REWARD' AND tbl_trans.trans_winlose <> 'QB' then
trans_winloseamount Else 0 End) BETHOST,
Sum(Case When tbl_trans.trans_winlose = 'QB' then
trans_winloseamount Else 0 End) QB,
Sum(Case When tbl_trans.trans_type = 'REWARD' then
trans_winloseamount Else 0 End) reward ,
Sum(sum(BETHOST)+sum(QB)+sum(reward)) totalsum
FROM tbl_trans
GROUP BY trans_username
i need to totalsum of BETHOST,QB and reward
how to sum of this Sum(sum(BETHOST)+sum(QB)+sum(reward)) totalsum
pls try this
sum(SELECT(BETHOST))+sum(SELECT(QB))+sum(SELECT(reward)) AS totalsum

Methods of speeding up a MySQL Query which has 12 subqueries

The following query returns the correct data but I'd like to see if there's a better way of doing this. The query should return the number of cases for each month within a 12 month period where a record exists within the past 2 months. The idea is to get number of accounts that ordered during the month in question and at least one of the previous 2 months. Also, please note that every value in the table for data_date will always be the 1st of the month.
SELECT
sum(
case
WHEN a.data_date = '2013-03-01'
and exists(
select 1 from sales mth1
where mth1.client_id = a.client_id
and
data_date BETWEEN '2013-01-01'
and
'2013-02-01'
)
then case_qty
ELSE 0 END
) AS M1 ,
sum(
case
WHEN a.data_date = '2013-04-01'
and exists(
select 1 from sales mth2
where mth2.client_id = a.client_id
and mth2.data_date BETWEEN '2013-02-01'
and
'2013-03-01'
)
then case_qty
ELSE 0 END
) AS M2 ,
sum( case WHEN a.data_date = '2013-05-01' and exists( select 1 from sales mth3 where mth3.client_id = a.client_id and mth3.data_date BETWEEN '2013-03-01' and '2013-04-01' ) then case_qty ELSE 0 END) AS M3 ,
sum( case WHEN a.data_date = '2013-06-01' and exists( select 1 from sales mth4 where mth4.client_id = a.client_id and mth4.data_date BETWEEN '2013-04-01' and '2013-05-01' ) then case_qty ELSE 0 END) AS M4 ,
sum( case WHEN a.data_date = '2013-07-01' and exists( select 1 from sales mth5 where mth5.client_id = a.client_id and mth5.data_date BETWEEN '2013-05-01' and '2013-06-01' ) then case_qty ELSE 0 END) AS M5 ,
sum( case WHEN a.data_date = '2013-08-01' and exists( select 1 from sales mth6 where mth6.client_id = a.client_id and mth6.data_date BETWEEN '2013-06-01' and '2013-07-01' ) then case_qty ELSE 0 END) AS M6 ,
sum( case WHEN a.data_date = '2013-09-01' and exists( select 1 from sales mth7 where mth7.client_id = a.client_id and mth7.data_date BETWEEN '2013-07-01' and '2013-08-01' ) then case_qty ELSE 0 END) AS M7 ,
sum( case WHEN a.data_date = '2013-10-01' and exists( select 1 from sales mth8 where mth8.client_id = a.client_id and mth8.data_date BETWEEN '2013-08-01' and '2013-09-01' ) then case_qty ELSE 0 END) AS M8 ,
sum( case WHEN a.data_date = '2013-11-01' and exists( select 1 from sales mth9 where mth9.client_id = a.client_id and mth9.data_date BETWEEN '2013-09-01' and '2013-10-01' ) then case_qty ELSE 0 END) AS M9 ,
sum( case WHEN a.data_date = '2013-12-01' and exists( select 1 from sales mth10 where mth10.client_id = a.client_id and mth10.data_date BETWEEN '2013-10-01' and '2013-12-01' ) then case_qty ELSE 0 END) AS M10 ,
sum( case WHEN a.data_date = '2014-01-01' and exists( select 1 from sales mth11 where mth11.client_id = a.client_id and mth11.data_date BETWEEN '2013-11-01' and '2013-12-01' ) then case_qty ELSE 0 END) AS M11
FROM sales as a
INNER JOIN Products AS P ON P.product_id = a.product_id
WHERE a.client_id IN ('123')
AND a.data_date BETWEEN '2013-03-01' AND '2013-12-01' AND a.case_qty > 0;
Here's a screen shot of the explain
Here's a screen shot of the indexes
change
data_date BETWEEN '2013-01-01' and '2013-02-01'
to
data_date in ('2013-01-01', '2013-01-02',.....,...'2013-02-01' )
but i would turn this whole query into sum cases then use a wrapper to pull out the accounts i need.
From your query it seems like you want the years sales for a product in an entire year. Or something to that affect. So from your data you are almost trying to create a pivot. I had a simlar problem and solved it like this
select
p.product_id,
s.client_id,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201301) then ifnull(case_qty,0) else 0 end) period1,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201301, 201302) then ifnull(case_qty,0) else 0 end) period2,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201301, 201302, 201303) then ifnull(case_qty,0) else 0 end) period3,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201302, 201303, 201304) then ifnull(case_qty,0) else 0 end) period4,
sum(case when DATE_FORMAT(a.data_date,'%Y%m') in (201303, 201304, 201305) then ifnull(case_qty,0) else 0 end) period5,
.
.
.
up to period12
from
sales s
where
a.data_date between '2013-03-01' and '2013-12-31' and
s.client_id = some_value
group by
p.product_id,
s.client_id
Note that the performance of the query has increased drastically since you are only doing a single scan of your sales table (depending on what's in your where clause and indexes). To speed it up you would need indexes on say client_id and data_date for example.
Ideally this query would be run for a report or something where the start and end data is fixed and all the user can change is the year of that date. I wasn't sure if you wanted to group by product_id since in your query you aren't, but you can always remove it to get total per client.
I have adjusted the query based on my understanding in your comments. I am not 100% sure if you can use the keyword 'in' in a case statement. You could alternatively have more case statements.

Counting number of Sales from two tables

I am using SUM ( CASE WHEN ) to count number of Yes and No, it work fine.
I am havin problem counting number of matching mobile number from two tables. It dont seem to be counting correctly.
There is a MobileNO field in dairy table and mobile field in the sales table
SELECT
D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'No' THEN 1 ELSE 0 END) as No,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
(SELECT SUM(CASE WHEN D.MobileNo = S.mobile THEN 1 ELSE 0 END) from sales as S) as Sales,
COUNT(*) as TOTAL FROM dairy as D
WHERE source = 'Company' AND UNIX_TIMESTAMP(CheckDate) >= 1293840000 AND UNIX_TIMESTAMP(CheckDate) <= 1322697600
group by D.Username order by TOTAL DESC
SELECT
D.Username,
SUM(CASE WHEN D.type = 'Yes' THEN 1 ELSE 0 END) as Yes,
SUM(CASE WHEN D.type = 'No' THEN 1 ELSE 0 END) as No,
SUM(CASE WHEN D.type = '' THEN 1 ELSE 0 END) as Other,
SUM(CASE WHEN S.mobile IS NULL THEN 0 ELSE 1 END) as Sales,
COUNT(*) as TOTAL
FROM dairy as D
LEFT JOIN (SELECT DISTINCT mobile FROM sales) as S ON D.MobileNo = S.mobile
WHERE source = 'Company' AND UNIX_TIMESTAMP(CheckDate) >= 1293840000 AND UNIX_TIMESTAMP(CheckDate) <= 1322697600
group by D.Username order by TOTAL DESC