MYSQL select info from sum within the query - mysql

this query works but pulls all results. I would like it to only pull results that are not 0.00 which is the totaldue. This is calculated within the query but I do not know how to exclude results with 0.00?
SELECT name,
SUM(IF(timeperiod='0',totalinv-paidtotal,0)) AS p0030,
SUM(IF(timeperiod='30',totalinv-paidtotal,0)) AS p3060,
SUM(IF(timeperiod='60',totalinv-paidtotal,0)) AS p6090,
SUM(IF(timeperiod='90',totalinv-paidtotal,0)) AS p9000,
SUM(totalinv)-SUM(paidtotal) AS totaldue
FROM
(
SELECT primary_key, name, timeperiod, totalinv, SUM(paidtotal) as paidtotal
FROM
(
SELECT
a.primary_key,
a_name AS name,
CAST(totalinv AS DECIMAL(10,2)) as totalinv,
CAST(IFNULL(amount,0) AS DECIMAL(10,2)) as paidtotal,
CASE
WHEN invoicedate > DATE_SUB(STR_TO_DATE($today,'%Y%m%d'),INTERVAL 29 DAY) THEN '0'
WHEN invoicedate > DATE_SUB(STR_TO_DATE($today,'%Y%m%d'),INTERVAL 59 DAY) AND invoicedate <= DATE_SUB(STR_TO_DATE($today,'%Y%m%d'),INTERVAL 29 DAY) THEN '30'
WHEN invoicedate > DATE_SUB(STR_TO_DATE($today,'%Y%m%d'),INTERVAL 89 DAY) AND invoicedate <= DATE_SUB(STR_TO_DATE($today,'%Y%m%d'),INTERVAL 29 DAY) THEN '60'
ELSE '90'
END AS timeperiod
FROM $mysql_billing a
LEFT OUTER JOIN $mysql_billing_dates b ON a.primary_key = b.id
WHERE $today >= invoicedate
AND $totaldue!='0.00'
AND void=''
) foo
GROUP BY primary_key, name, timeperiod
) bar
GROUP BY name
ORDER BY name ASC

You are just missing a HAVING at the very end:
....
GROUP BY name
HAVING totaldue != 0
ORDER BY name ASC
That will allow you to select on your calculated/grouped column.

Related

Minimum and Maximum Count of Overlapping Bookings

I have a booking system that has multiple simultaneous bookings with a count number for each. I need to get the minimum and maximum for a specified date-range (for a day, in this case). I found some good code here, which works great in the test. But in my implementation, it fails in this particular instance:
It does not count bookings that start prior to the query-range and end within the query-range.
How do I fix this?
Here is an example:
This booking exists with these properties:
listings (an ID that multiple bookings can have, but only one in this case): 2f23f23f
date_start: 2016-01-15 08:00:00
date_end: 2016-01-17 08:00:00
state: active
count: 1
Result:
min_count: 0
max_count: 0
It should return:
min_count: 0
max_count: 1
If we query the very same, but with date range 2016-01-16 00:00:00 - 2016-01-16 23:59:59, it returns the correct answer:
min_count: 1
max_count: 1
Here is the MYSQL:
SELECT
MAX(simultaneous) AS max_count,
MIN(simultaneous) AS min_count
FROM (
SELECT IFNULL(SUM(
(
CASE WHEN (
listings = '2f23f23f'
AND
(state = 'active')
)
THEN count
ELSE 0
END
)
),0) AS simultaneous
FROM bookings RIGHT JOIN (
SELECT date_start AS boundary
FROM bookings
WHERE date_start BETWEEN '2016-01-17 00:00:00' AND '2016-01-17 23:59:59'
UNION
SELECT date_end
FROM bookings
WHERE date_end BETWEEN '2016-01-17 00:00:00' AND '2016-01-17 23:59:59'
UNION
SELECT MAX(boundary)
FROM (
SELECT MAX(date_start) AS boundary
FROM bookings
WHERE date_start <= '2016-01-17 00:00:00'
UNION ALL
SELECT MAX(date_end)
FROM bookings
WHERE date_end <= '2016-01-17 23:59:59'
) t
) t ON date_start <= boundary AND boundary < date_end
LEFT OUTER JOIN cart ON cart_bookings = id
GROUP BY boundary
) t
Whew, ok, here's the answer. The original evidently wasn't complete. It needed to include the start/end dates of the time-range being requested.
UNION
SELECT :date_start
UNION
SELECT :date_end
Complete code:
SELECT
MAX(simultaneous) AS max_count,
MIN(simultaneous) AS min_count
FROM (
SELECT IFNULL(SUM(
(
CASE WHEN (
listings = '2f23f23f'
AND
(state = 'active')
)
THEN count
ELSE 0
END
)
),0) AS simultaneous
FROM bookings RIGHT JOIN (
SELECT date_start AS boundary
FROM bookings
WHERE date_start BETWEEN '2016-01-17 00:00:00' AND '2016-01-17 23:59:59'
UNION
SELECT date_end
FROM bookings
WHERE date_end BETWEEN '2016-01-17 00:00:00' AND '2016-01-17 23:59:59'
UNION
SELECT MAX(boundary)
FROM (
SELECT MAX(date_start) AS boundary
FROM bookings
WHERE date_start <= '2016-01-17 00:00:00'
UNION ALL
SELECT MAX(date_end)
FROM bookings
WHERE date_end <= '2016-01-17 23:59:59'
) t
UNION
SELECT :date_start
UNION
SELECT :date_end
) t ON date_start <= boundary AND boundary < date_end
LEFT OUTER JOIN cart ON cart_bookings = id
GROUP BY boundary
) t

Get rows if one or the other or both fields match

I need to fetch promotions by location where I have the following logic:
City = Oslo, Country = No : True
City = '', Country = No : True
City = Bergen, Country = No : False
The query I have to so far is this:
SELECT *
FROM promotion
WHERE date_start <= DATE_ADD(CURDATE(), INTERVAL 14 DAY)
AND date_end >= CURDATE()
AND fk_countryID = 'NO'
order by date_start ASC
This returns 5 rows.
- Once city is blank.
- One city is Bergen
Wanted result: 4 rows where one city is blank.
I also tried this:
SELECT id, name, city, fk_countryID, date_start, date_end
FROM promotion
WHERE date_start <= DATE_ADD(CURDATE(), INTERVAL 14 DAY)
AND date_end >= CURDATE()
AND city = '' || city = 'Oslo'
AND fk_countryID = 'NO'
order by date_end ASC
This does return all rows where city is either blank or 'Oslo' and country id is 'no', but it also returns rows outside the date constraints.
How can I achieve this? Any help appreciated.
I eventually found the answer:
SELECT id, name, city, fk_countryID, date_start, date_end
FROM promotion
WHERE date_start <= DATE_ADD(CURDATE(), INTERVAL 14 DAY)
AND date_end >= CURDATE()
AND city IN ('','Oslo')
AND fk_countryID = 'NO'
order by date_end ASC

Retrieve data for specific months

MySQL Query is like this
SELECT MONTHNAME(access_date) as date,
DATE_FORMAT( access_date, '%m/%Y' ) as month_date ,
COUNT( log_id ) as total_count
FROM user_activity_log
WHERE dam_id = (
SELECT dam_id
FROM dam_content_details
WHERE content_type= '$content_type'
)
AND access_date >= last_day(NOW() - INTERVAL ($month) MONTH)
GROUP BY MONTH( access_date )
ORDER BY access_date ASC
i will pass the numbers like 1,2,3.... then its giving value for that month.
The problem i faced is it retrieving the data per 30 days,60 days like that. I want if i will write $month = '1; then it should return the current month data & previous month data starting from day 1.
My sample output - $month = 2
date month_date total_count
--------- ------------ -----------
December 12/2013 4
January 01/2014 1
I want for december it should calculate from 12/01/2013. 1st December 2013. Any idea how to solve it ?
You just have to remove = from >=.
Try this:
SELECT MONTHNAME(access_date) as date,
DATE_FORMAT( access_date, '%m/%Y' ) as month_date ,
COUNT( log_id ) as total_count
FROM user_activity_log
WHERE dam_id = (SELECT dam_id FROM dam_content_details WHERE content_type= '$content_type') AND
access_date > LAST_DAY(NOW() - INTERVAL (($month)+1) MONTH)
GROUP BY MONTH( access_date )
ORDER BY access_date ASC

mysql Select from Select

I have this query:
SELECT DATE( a.created_at ) AS order_date, count( * ) as cnt_order
FROM `sales_order_item` AS a
WHERE MONTH( a.created_at ) = MONTH( now())-1
GROUP BY order_date
which will return result something like this (snapshot only otherwise will return per 31 days):
order_date cnt_order
2012-08-29 580
2012-08-30 839
2012-08-31 1075
and my full query is selecting based on above selection:
SELECT order_date
, MAX(cnt_order) AS highest_order
FROM (
SELECT DATE (a.created_at) AS order_date
, count(*) AS cnt_order
FROM `sales_order_item` AS a
WHERE MONTH(a.created_at) = MONTH(now()) - 1
GROUP BY order_date
) AS tmax
But it result :
order_date highest_order
2012-08-01 1075
Which has the date wrong and always pick the first row of date where it suppose 2012-08-31. Maybe this is a simple error that I dont know. So how to get the date right point to 2012-08-31? Any help would be great.
You could try ordering the sub query result set; something like:
SELECT
DATE (a.created_at) AS order_date,
COUNT(*) AS cnt_order
FROM
`sales_order_item` AS a
WHERE
MONTH(a.created_at) = MONTH(now()) - 1
GROUP BY
order_date
ORDER BY
cnt_order DESC
You can add ORDER BY order_date DESC in subquery.

SQL: Nested queries based on values of a column

I have queried a table with the following query
select content_type_code_id
, price
, count(price) AS PRICECOUNT
from dbo.transaction_unrated
where transaction_date >= '2012/05/01'
and transaction_date < '2012/06/01'
and content_provider_code_id in (1)
group by content_type_code_id, price
ORDER BY price ASC
which produces the following result set
content_type_code_id price PRICECOUNT
1 -1.99 1
1 -0.99 1
1 0.99 178
1 1.99 786
But I want a result set like this:
content_type_code_id price Debits Credits
1 0.99 178 1
1 1.99 786 1
(Negative price as credit and positive price as debit)
try this one
select content_type_code_id
, ABS(price)
, count(IF(price >= 0,1,null)) AS debits,
, count(IF(price < 0,1,null)) AS credits,
from dbo.transaction_unrated
where transaction_date >= '2012/05/01'
and transaction_date < '2012/06/01'
and content_provider_code_id in (1)
group by content_type_code_id, ABS(price)
ORDER BY price ASC
Try this:
SELECT content_type_code_id
, price * -1
, COUNT(price) AS PRICECOUNT
, (
SELECT COUNT (deb.price)
FROM dbo.transaction_unrated deb
WHERE deb.transaction_date >= '2012/05/01'
AND deb.transaction_date < '2012/06/01'
AND deb.content_provider_code_id IN (1)
AND deb.price = ( dbo.transaction_unrated.price * -1 )
)
FROM dbo.transaction_unrated
WHERE transaction_date >= '2012/05/01'
AND transaction_date < '2012/06/01'
AND content_provider_code_id IN (1)
AND price < 0
GROUP BY content_type_code_id
, price
, 4
ORDER BY price ASC