most recent entry made in table bases on one year interval mysql - mysql

Using the following sqlfiddle here How would I find the most recent payment made between the months of 2012-04-1 and 2012-03-31 using the case statement as in the previous queries
I tried this:
max(case when py.pay_date >= STR_TO_DATE(CONCAT(2012, '-04-01'),'%Y-%m-%d') and py.pay_date <= STR_TO_DATE(CONCAT(2012, '-03-31'), '%Y-%m-%d') + interval 1 year then py.amount end) CURRENT_PAY
However the answer I am getting is incorrect, where the actual answer should be:(12, '2012-12-12', 20, 1)
Please Provide me with some assistance, thank you.

Rather than a CASE inside your MAX() aggregate, that condition belongs in the WHERE clause. This joins against a subquery which pulls the most recent payment per person_id by joining on MAX(pay_date), person_id.
SELECT payment.*
FROM
payment
JOIN (
SELECT MAX(pay_date) AS pay_date, person_id
FROM payment
WHERE pay_date BETWEEN '2012-04-01' AND DATE_ADD('2012-03-31', INTERVAL 1 YEAR)
GROUP BY person_id
) maxp ON payment.person_id = maxp.person_id AND payment.pay_date = maxp.pay_date
Here is an updated fiddle with the ids corrected in your table (since a bunch of them were 15). This returns record 18, for 2013-03-28.
Update
After seeing the correct SQL fiddle... To incorporate the results of this query into your existing one, you can LEFT JOIN against it as a subquery on p.id.
select p.name,
v.v_name,
sum(case when Month(py.pay_date) = 4 then py.amount end) april_amount,
(case when max(py.pay_date)and month(py.pay_date)= 4 then py.amount else 0 end) max_pay_april,
sum(case
when Month(py.pay_date) = Month(curdate())
then py.amount end) current_month_amount,
sum(case
when Month(py.pay_date) = Month(curdate())-1
then py.amount end) previous_month_amount,
maxp.pay_date AS last_pay_date,
maxp.amount AS last_pay_amount
from persons p
left join vehicle v
on p.id = v.person_veh
left join payment py
on p.id = py.person_id
/* LEFT JOIN against the subquery: */
left join (
SELECT MAX(pay_date) AS pay_date, amount, person_id
FROM payment
WHERE pay_date BETWEEN '2012-04-01' AND DATE_ADD('2012-03-31', INTERVAL 1 YEAR)
GROUP BY person_id, amount
) maxp ON maxp.person_id = p.id
group by p.name,
v.v_name

Related

View doesn't show same result as command with subquery on mariadb

Dears,
I tried to create a view that sumarize transaction per category (row) and months (columns) on one year as this :
SELECT counterpart.id_category as catid, category AS Category, (
SELECT COALESCE(SUM(amount), 0)
FROM transaction
INNER JOIN counterpart
ON transaction.id_counterpart = counterpart.id_counterpart
WHERE YEAR(date) = YEAR(now())
AND MONTH(date) = 1
AND id_category = catid
) AS Jan, [...]
FROM transaction
INNER JOIN counterpart
ON transaction.id_counterpart = counterpart.id_counterpart
INNER JOIN category
ON counterpart.id_category = category.id_category
WHERE transaction.id_user = 2
AND YEAR(date) = YEAR(now())
GROUP BY category
I don't know if it's a good way or not, at least it works as single command but not as view.
On view, the WHERE id_category = catid for subquery doesn't work properly.
Thank you.
I suspect conditional aggregation would be more appropriate and quicker than a lot of sub queries.
for example
SELECT counterpart.id_category as catid, category AS Category,
sum(case when month(date) = 1 then 1 else 0 end) as Jan,
sum(case when month(date) = 2 then 1 else 0 end) as feb,
sum(case when month(date) = 3 then 1 else 0 end) as Mar
FROM transaction
INNER JOIN counterpart
ON transaction.id_counterpart = counterpart.id_counterpart
INNER JOIN category
ON counterpart.id_category = category.id_category
WHERE transaction.id_user = 2
AND YEAR(date) = YEAR(now())
GROUP BY counterpart.id_category,category

Case When Exists In Subquery

I am trying to check whether an ID is present in a subquery. I have ran just the subquery and it produces a list of all the ID's which have a fee against it, so what I want to do is check whether the ID in the main query is present in the subquery. If it's present then return 1, else return 0.
This is an easy query but I have no idea where i'm going wrong, I tried using exists rather than in but this does not work either.
case when debtor._rowid in (
select distinct note.debtorid from note
left join debtor on note.debtorid = debtor._rowid
left join fee on fee.debtorid = debtor._rowid
where fee.type = "Enforcement" and note.type = "Stage")
then 1 else 0 end) as `Enforcement`
Below is the entire code, when I remove the above code from the main query below, it works perfectly, so there's something wrong in my case statement.
with cte_1
as
(
select
debtor._rowid as casref
,concat(date_format(date_sub(debtor._createddate, interval 3 month), '%y'), '/', date_format(date_add(debtor._createddate, interval 9 month), '%y')) as `F/Y`
,date_format(debtor._createddate, '%M %Y') as `Loaded Month`
,ifnull(concat(date_format(date_sub(debtor.offence_date, interval 3 month), '%y'), '/', date_format(date_add(debtor.offence_date, interval 9 month), '%y')),'-') as `LO F/Y`
,coalesce(date_format(debtor.offence_date,'%M %Y'),'-') as `Liability Order Month`
,scheme.name as `Scheme`
,branch.name as `Branch`
,count(debtor._rowid) as `Cases Received`
,count(debtor.linkid) as `LinkID`
,(case
when concat(date_format(date_sub(debtor._createddate, interval 3 month), '%y'), '/', date_format(date_add(debtor._createddate, interval 9 month), '%y'))
= ifnull(concat(date_format(date_sub(debtor.offence_date, interval 3 month), '%y'), '/', date_format(date_add(debtor.offence_date, interval 9 month), '%y')),'-')
then 1 else 0 end ) as `Same Year`
, case when debtor._rowid in (
select distinct note.debtorid from note
left join debtor on note.debtorid = debtor._rowid
left join fee on fee.debtorid = debtor._rowid
where fee.type = "Enforcement"
and note.type = "Stage")
then 1 else 0 end) as `Enforcement`
from debtor
left join clientscheme on debtor.clientschemeID = clientscheme._rowid
left join scheme on clientscheme.schemeID = scheme._rowid
left join branch on clientscheme.branchID = branch._rowid
left join fee on debtor._rowid = fee.debtorid
left join note on debtor._rowid = note.debtorid
where clientscheme.branchID in (1,10,24)
and debtor._createddate >= '2017-04-01'
group by debtor._rowid
)
,
cte_2
as
(
select
`F/Y`
,`Loaded Month`
,`LO F/Y`
,`Liability Order Month`
,`Scheme`
,`Branch`
,sum(`Cases Received`) as `Case Count`
,sum(`LinkID`) as `Linked Accounts`
,sum(`Same Year`) as `In Year LO`
,sum(Enforcement) as `Enforcement Applied`
from cte_1
group by
`Loaded Month`
,`Liability Order Month`
,`Scheme`
, `Branch`
)
select
`F/Y`
,`Loaded Month`
,`LO F/Y`
,`Liability Order Month`
,`Scheme`
,`Branch`
,`Case Count`
,`Linked Accounts`
,round((`Linked Accounts`/`Case Count`),2) * 100 as `% of Linked Accounts`
,round((`In Year LO`/`Case Count`),2) * 100 as `In Year LO's`
,`Enforcement Applied`
from cte_2
It appears that you want to logically check if, for a given record in the result set, a _noteid value from the debtor table matches to a debtors from the note table. You could rephrase your query as follows:
SELECT
(d._rowid = n.debtorid) AS `Enforcement Allocated`
FROM note n
LEFT JOIN debtor d
ON n.debtorid = d._rowid
LEFT JOIN fee f
ON f.debtorid = d._rowid
WHERE
f.type = 'Enforcement' AND n.type = 'Stage';
Note that since the output of your CASE expression is just 1 or 0, you may take advantage of that MySQL allows boolean expressions as values.

Total the aggregate in Select Case Statement

Is there a way to get a total from the aggregate in each select case statement? The following gives me the correct total by listing the total for each month in a column but I would like to have a single total for each case statement.
SELECT SUM(
CASE WHEN dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2016-12-31' THEN dbo.bill_t_ARTransaction.Amount ELSE 0 END
) AS 'Dec16'
, SUM(
CASE WHEN dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31' THEN dbo.bill_t_ARTransaction.Amount ELSE 0 END
) AS 'JAN17'
FROM dbo.bill_t_ARTransaction
INNER JOIN dbo.bill_t_TripTicket ON (
dbo.bill_t_ARTransaction.RunNumber = dbo.bill_t_TripTicket.RunNumber
)
INNER JOIN dbo.med_m_Company ON (
dbo.bill_t_TripTicket.CompanyCode = dbo.med_m_Company.CompanyCode
)
WHERE dbo.bill_t_TripTicket.CompanyCode = '105'
AND dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
GROUP BY dbo.bill_t_ARTransaction.TransactionDate
I just formated your SQL - so it will be more readable for human beings - and put it in a Subselect.
In the outer Select i just added the SUM of the two calculated columns
SELECT sums.*
,SUM(sums.DEC16 + sums.JAN17) AS TOTAL_SUM
FROM (
SELECT SUM( CASE WHEN dbo.bill_t_ARTransaction.TransactionDate
BETWEEN '2000-01-01'
AND '2016-12-31'
THEN dbo.bill_t_ARTransaction.Amount
ELSE 0
END
) AS DEC16
,SUM( CASE WHEN dbo.bill_t_ARTransaction.TransactionDate
BETWEEN '2000-01-01'
AND '2017-01-31'
THEN dbo.bill_t_ARTransaction.Amount
ELSE 0
END
) AS JAN17
FROM dbo.bill_t_ARTransaction
INNER JOIN dbo.bill_t_TripTicket
ON dbo.bill_t_ARTransaction.RunNumber = dbo.bill_t_TripTicket.RunNumber
INNER JOIN dbo.med_m_Company
ON dbo.bill_t_TripTicket.CompanyCode = dbo.med_m_Company.CompanyCode
WHERE dbo.bill_t_TripTicket.CompanyCode = '105'
AND dbo.bill_t_ARTransaction.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
GROUP BY dbo.bill_t_ARTransaction.TransactionDate
) sums
I think you just want to get right of the GROUP BY:
SELECT SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2016-12-31'
THEN ba.Amount ELSE 0
END) AS Dec16,
SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
THEN ba.Amount ELSE 0
END) AS JAN17
FROM dbo.bill_t_ARTransaction ba INNER JOIN
dbo.bill_t_TripTicket bt
ON ba.RunNumber = bt.RunNumber INNER JOIN
dbo.med_m_Company c
ON bt.CompanyCode = c.CompanyCode
WHERE bt.CompanyCode = '105' AND
ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31';
Note the other changes I made to the query:
I removed the single quotes from the column aliases. Single quotes should only be used for string and date values (using them for column aliases is allowed but can cause confusion).
The tables are given aliases.
The column names are qualified with the aliases (the query is easier to write and to read.
Note that '105' should not have quotes, if CompanyCode is numeric.
I think the query can be simplified to:
SELECT SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2016-12-31'
THEN ba.Amount ELSE 0
END) AS Dec16,
SUM(CASE WHEN ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31'
THEN ba.Amount ELSE 0
END) AS JAN17
FROM dbo.bill_t_ARTransaction ba INNER JOIN
dbo.bill_t_TripTicket bt
ON ba.RunNumber = bt.RunNumber
WHERE bt.CompanyCode = 105 AND
ba.TransactionDate BETWEEN '2000-01-01' AND '2017-01-31';
The Company table does not appear to be being used.
You can do this:
SELECT DATENAME(MONTH, Transaction.TransactionDate) + RIGHT(YEAR(Transaction.TransactionDate), 2) AS MonthYear
, SUM(Transaction.Amount) AS Amount
FROM dbo.bill_t_ARTransaction Transaction
INNER JOIN dbo.bill_t_TripTicket Ticket
ON Transaction.RunNumber = Ticket.RunNumber
INNER JOIN dbo.med_m_Company Company
ON Ticket.CompanyCode = Company.CompanyCode
WHERE Ticket.CompanyCode = '105'
AND Transaction.TransactionDate >= '2000-01-01'
AND Transaction.TransactionDate < '2017-02-01'
GROUP BY DATENAME(MONTH, Transaction.TransactionDate) + RIGHT(YEAR(Transaction.TransactionDate), 2)
Assuming dbo.bill_t_ARTransaction.TransactionDate is a datetime(2): Are you aware that in 'DEC16' you are missing transaction from (as an example) 2016-12-31 11:00:00? BETWEEN is inclusive on both sides, and dates are defaulted to midnight (00:00:00) if no time component is defined. I altered the WHERE clause accordingly. I also added aliases to help the readability.

SQL statement for GROUP BY

I am really stucked with one sql select statement.
This is output/result which I get from sql statement below:
WHAT I need: I need to have columns assignedVouchersNumber and usedVouchersNumber together in one row by msisdn. So for example if you can see "msisdn" 723709656 there are two rows now.. one with assignedVouchersNumber = 1 and second with assignedVouchersNumber = 1 too.
But I need to have it in one row with assignedVouchersNumber = 2. Do you now where is the problem?
SELECT eu.msisdn,
eu.id as userId,
sum(case ev.voucherstate when '1' then 1 else 0 end) as assignedVouchersNumber,
sum(case ev.voucherstate when '2' then 1 else 0 end) as usedVouchersNumber,
ev.extra_offer_id,
ev.create_time,
ev.use_time,
ev.id as voucherId,
ev.voucherstate
FROM extra_users eu
JOIN (SELECT sn.msisdn AS telcislo,
stn.numberid
FROM stats_number sn
JOIN stats_target_number AS stn
ON ( sn.numberid = stn.numberid )
WHERE stn.targetid = 1) xy
ON eu.msisdn = xy.telcislo
JOIN extra_vouchers AS ev
ON ( eu.id = ev.extra_user_id )
WHERE ev.create_time BETWEEN '2012-07-23 00:00:00' AND '2013-08-23 23:59:59'
AND ev.use_time <= '2013-08-23 23:59:59'
AND ev.use_time >= '2012-07-23 00:00:00'
AND ev.voucherstate IN ( 1, 2 )
AND Ifnull(ev.extra_offer_id IN( 2335, 3195, 30538 ), 1)
GROUP BY eu.msisdn, ev.extra_offer_id, ev.voucherState
ORDER BY eu.msisdn ASC
You have two different extra_offer_id for same msisdn and VouchersNumber. Thats why you get two rows.
I got it... there should not be groupping by ev.voucherState in
GROUP BY eu.msisdn, ev.extra_offer_id, ev.voucherState
After then I have removed ev.voucherState it is working now.

Finding the Most current entry for a month using mysql

I am having a mysql problem I am trying to find both the most current payment value, and, for a particular month (in this query I'm using April). Link to the sqlfillde is here
(case when max(py.pay_date)and month(py.pay_date)= 4 then amount else 0 end) max_pay_april,
This is what I have but it doesn't seem to be working. The most current payment value is: (5, '2012-04-20', 90,) therefore it would be 90 I would really appreciate some help please.
How about this:
select p.name,
v.v_name,
sum(case when Month(py.pay_date) = 4 then amount end) april_amount,
max(case
when month(py.pay_date)= 4
and py.pay_date = (select max(pay_date)
from payment
where month(pay_date) =4 )
then amount else 0 end) max_pay_april,
sum(case
when Month(py.pay_date) = Month(curdate())
then amount end) current_month_amount,
sum(case
when Month(py.pay_date) = Month(curdate())-1
then amount end) previous_month_amount
from persons p
left join vehicle v
on p.id = v.person_veh
left join payment py
on p.id = py.person_id
group by p.name,
v.v_name
see SQL Fiddle with demo