UNION issue in select sub-query - mysql

In the below code, how do I combine MRR_Created with MRR_Destroyed in a UNION so it only shows the next number? Right now the query is correct but I don't need to see the increase/decrease separately.
select account.email, account.vip, datediff(now(), account.date_created) AS Age,
(select sum(account_subscription.next_invoice_price) as ActiveMRR
from account_subscription
where account_subscription.status = 'active'
and account_subscription.acctid = account.acctid
) as MRR,
(select count(account_subscription.subid) as Churn
from account_subscription
where account_subscription.date_created between DATE_ADD(NOW(), INTERVAL -2880 MINUTE) and NOW()
and account_subscription.date_closed between DATE_ADD(NOW(), INTERVAL -2880 MINUTE) and NOW()
and account_subscription.acctid = account.acctid
) as Churn,
(select sum(account_subscription.next_invoice_price) as MRR
from account_subscription
where date(account_subscription.date_created) = date(curdate())
and account_subscription.acctid = account.acctid
) as MRR_Created,
(select sum(account_subscription.next_invoice_price) as MRR
from account_subscription
where date(account_subscription.date_closed) = date(curdate())
and account_subscription.acctid = account.acctid
) as MRR_Destroyed,
concat("https://sitetest.com?ACCTID=",account.acctid) as URL
from account
where account.status = 'active'
and (
account.type in ('affiliate', 'customer', 'customer_freetrial', 'customer_duplicate', 'customer_match')
or account.type is null
)
group by account.acctid
order by MRR desc

Not sure if you really need a UNION here. Try replacing
(select sum(account_subscription.next_invoice_price) as MRR
from account_subscription
where date(account_subscription.date_created) = date(curdate())
and account_subscription.acctid = account.acctid
) as MRR_Created,
(select sum(account_subscription.next_invoice_price) as MRR
from account_subscription
where date(account_subscription.date_closed) = date(curdate())
and account_subscription.acctid = account.acctid
) as MRR_Destroyed,
with
(select sum(account_subscription.next_invoice_price) as MRR
from account_subscription
where (date(account_subscription.date_created) = date(curdate())
or date(account_subscription.date_closed) = date(curdate()))
and account_subscription.acctid = account.acctid
) as MRR_Created,
Hope this helps!

Related

How to get the deals which are expiring today with MySQL Query

How do I get the today's deals only with deal_expiry_date_time is greater that current time?
SELECT *
FROM `deals` AS `d`
WHERE d.status = 'Active' AND d.deal_end_date_time BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 0 DAY)
AND d.created_by_id = '11'
ORDER BY `d`.`deal_id` ASC
LIMIT 5
To select everything from now to the end of the day
SELECT *
FROM `deals` AS `d`
WHERE d.status = 'Active'
AND d.deal_end_date_time BETWEEN NOW() AND CONCAT(CURDATE(), " 23:59:59")
AND d.created_by_id = '11'
ORDER BY `d`.`deal_id` ASC
LIMIT 5
To select everything from now to tomorrow
SELECT *
FROM `deals` AS `d`
WHERE d.status = 'Active'
AND d.deal_end_date_time BETWEEN NOW() AND NOW() + INTERVAL 1 DAY;
AND d.created_by_id = '11'
ORDER BY `d`.`deal_id` ASC
LIMIT 5
My suggestion is to have both datetime and date in your table to avoid loosing indexes filtering with funcs
Not sure if following sql is what you want or not, if you post some sample data and expected result, then we will understand your logic better.
SELECT *
FROM `deals` AS `d`
WHERE d.status = 'Active'
AND d.deal_end_date_time >= NOW()
AND DATE(d.deal_end_date_time) = CURRENT_DATE
AND d.created_by_id = '11'
ORDER BY `d`.`deal_id` ASC
LIMIT 5
SELECT *
FROM `deals` AS `d`
WHERE d.status = 'Active' AND CAST( d.deal_end_date_time AS date ) = CURRENT_DATE
AND d.created_by_id = '11'
ORDER BY `d`.`deal_id` ASC
LIMIT 5

How to change format of the MySQL result?

I have a complex mysql query language, including several sub queries and my final result is as below. There is something that I am dealing with it and I can't solve it and this is a way result is being presented. I am wondering to know how can i change the structure of the result in a way that the result is being presented only in one row and I don't want to see NULL fields. I mean something like below
This is mysql query
select count(*) as userRetentionSameDay, null as 'userRetentionDiffDay' from (SELECT date(`timestamp`), `user_xmpp_login`
FROM table1
WHERE DATE(`timestamp` ) = CURDATE() - INTERVAL 1 DAY) as res1
right join (select date(ts), user
from table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
and product_id REGEXP ("^(europe+$" )) as lej1
on lej1.user = res1.`user_xmpp_login`
where res1.`user_xmpp_login` IS not NULL
union all
select null as 'userRetentionSameDay', count(*) as userRetentionDiffDay from (SELECT date(`timestamp`), `user_xmpp_login`
FROM table1
WHERE DATE(`timestamp` ) = CURDATE() - INTERVAL 1 DAY) as res1
right join (select date(ts), user
from table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
and product_id REGEXP ("^(europe+$" )) as lej2
on lej2.user = res1.`user_xmpp_login`
where res1.`user_xmpp_login` IS NULL;
What are the recommended solutions to doing that?
try this.
SELECT A.userRetentionSameDay,B.userRetentionDiffDay FROM (
SELECT COUNT() AS userRetentionSameDay FROM
(
SELECT DATE(timestamp), user_xmpp_login
FROM table1
WHERE DATE(timestamp ) = CURDATE() - INTERVAL 1 DAY) AS res1
RIGHT JOIN (SELECT DATE(ts), USER
FROM table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
AND product_id REGEXP ("^(europe+$" )) AS lej1
ON lej1.user = res1.user_xmpp_login
WHERE res1.user_xmpp_login IS NOT NULL
) A,
(
SELECT COUNT() AS userRetentionDiffDay FROM (
SELECT DATE(timestamp), user_xmpp_login
FROM table1
WHERE DATE(timestamp ) = CURDATE() - INTERVAL 1 DAY
) AS res1
RIGHT JOIN (SELECT DATE(ts), USER
FROM table2
WHERE DATE(ts ) = CURDATE() - INTERVAL 1 DAY
AND product_id REGEXP ("^(europe+$" )
) AS lej2
ON lej2.user = res1.user_xmpp_login
WHERE res1.user_xmpp_login IS NULL
) B;

How to use if condition in where clause in mysql

I have a query that fetch records from two table. I want if condition in where clause with and operator.
Here is my code :
SELECT sfo.customer_id, sfo.increment_id FROM sales_flat_order sfo
INNER JOIN marketplace_partnertype mptype ON sfo.customer_id = mptype.partner_id
WHERE (mptype.type = 'free' AND sfo.status='complete') AND IF #mptype.type=='free' THEN ((DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 5 DAY ))ELSE (DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 3 DAY );
It shows syntax error near IF #mptype.type=='free'.
It should be appreciable if some help to solve this issues.
Syntax of If condition is:
IF(<cond-expr>, <then-expr>, <else-expr>)
If we change the condition it will be like :-
AND IF (#mptype.type=='free', (DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 5 DAY )) ,(DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 3 DAY ))
Query will look like:
SELECT sfo.customer_id, sfo.increment_id FROM sales_flat_order sfo
INNER JOIN marketplace_partnertype mptype ON sfo.customer_id = mptype.partner_id
WHERE (mptype.type = 'free' AND sfo.status='complete')AND IF (#mptype.type=='free', (DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 5 DAY )) ,(DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 3 DAY )))
The syntax is not correct, you can use case-when condition in the where condition as
SELECT sfo.customer_id, sfo.increment_id FROM sales_flat_order sfo
INNER JOIN marketplace_partnertype mptype ON sfo.customer_id = mptype.partner_id
WHERE (mptype.type = 'free' AND sfo.status='complete')
and
case
when #mptype.type = 'free' then DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 5 DAY )
else DATE( updated_at ) = DATE_SUB( CURDATE( ) , INTERVAL 3 DAY )
end
There's no need to use IF or CASE WHEN:
SELECT
sfo.customer_id,
sfo.increment_id
FROM
sales_flat_order sfo INNER JOIN marketplace_partnertype mptype
ON sfo.customer_id = mptype.partner_id
WHERE
(mptype.type = 'free' AND DATE(updated_at) = DATE_SUB(CURDATE(), INTERVAL 5 DAY)
OR (mptype.type = 'complete' AND DATE(updated_at) = DATE_SUB(CURDATE(), INTERVAL 3 DAY);
but if you want to use case when you could do it this way:
WHERE
mptype.type IN ('free', 'complete')
AND DATE(updated_at) = DATE_SUB(CURDATE(), INTERVAL CASE WHEN mptype.type='free' THEN 3 ELSE 5 END DAY)

issue combining two mysql queries

I have two queries I am looking to combine into one. This query will be called by backbone in a rails app. The final result should look like this. Thanks in advance.
Title Impressions Completed
Test 1234 500 34
SELECT title, count(*) as impressions FROM `stats`
WHERE `stats`.`user_id` = 2
AND (stats.event ='play' and videopos = '0')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59')
GROUP BY title;
SELECT title, count(*) as completed FROM `stats`
WHERE `stats`.`user_id` = 2
AND (stats.event ='completed')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59')
GROUP BY title;
try that :
SELECT title,(select count(*) FROM `stats` WHERE stats.event ='play' and videopos = '0' AND `stats`.`user_id` = 2 AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59') ) as impressions ,(select count(*) FROM `stats` WHERE stats.event ='completed' AND `stats`.`user_id` = 2 AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59') ) as completed
FROM `stats`
WHERE `stats`.`user_id` = 2
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59')
GROUP BY title;
If you just want to combine the result, use UNION/UNION ALL
SELECT title, count(*) as impressions FROM `stats`
WHERE `stats`.`user_id` = 2
AND (stats.event ='play' and videopos = '0')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59')
GROUP BY title
UNION
SELECT title, count(*) as completed FROM `stats`
WHERE `stats`.`user_id` = 2
AND (stats.event ='completed')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59')
GROUP BY title;
Try this :
SELECT title,
Sum(Case When `stats`.`user_id` = 2
AND (stats.event ='play' and videopos = '0')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59' Then 1 Else 0 End)
as impressions ,
Sum(Case When `stats`.`user_id` = 2
AND (stats.event ='completed')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59') Then 1 Else 0 End)
as completed
FROM `stats`
WHERE (`stats`.`user_id` = 2
AND (stats.event ='play' and videopos = '0')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59') )
OR
(`stats`.`user_id` = 2
AND (stats.event ='completed')
AND (date_time between '2014-03-08 00:00:00' and '2014-03-15 23:59:59') )
GROUP BY title;
btw, I am coming from ms-sql-server background but I checked on mysql case when syntax. And I typed in notepad, so untested. But I hope you catch the Sum Case When 1 0 idea and tweak it to your requirement..
I figured it out. This worked for me.
SELECT s.date as date, s.title as title,
count(F.id) as impressions,
count(D.event) as completed
FROM stats s
Left Join stats as F on s.id = F.id and F.event ='play' and F.videopos = '0'
Left Join stats as D on s.id = D.id and D.event = 'completed'
WHERE s.user_id = '2'
AND (s.date_time between '2014-03-08 00:00:00' and '2014-03-18 23:59:59')
AND s.title is not null
GROUP BY s.title

Setting user defined variables with joins

I have a query like below:
Result gives #sold_count:=SUM(I.quantity) = 10, but #sold_count = 0,
so calculations are all 0.
What should be wrong here?
SET #sold_count :=0;
SELECT
#sold_count:=SUM(I.quantity),
#sold_count,I.from_widget,COUNT(from_widget) as order_count,
(#sold_count * buy_price) as ciro,
(#sold_count * list_price) as liste_ciro,
(#sold_count * widget_price) as vitrin_ciro,
P.*
FROM
tbl_products P
LEFT JOIN tbl_order_items I on I.product_id = P.id
WHERE
P.publish_date BETWEEN DATE_SUB( CURDATE( ) ,INTERVAL 3 MONTH ) AND DATE_SUB( CURDATE( ) ,INTERVAL 0 MONTH )
GROUP BY I.from_widget,I.product_id
ORDER BY publish_date DESC
Don't use variables. Just:
SELECT
SUM(I.quantity),
I.from_widget,
COUNT(from_widget) AS order_count,
SUM(I.quantity) * buy_price AS ciro,
SUM(I.quantity) * list_price AS liste_ciro,
SUM(I.quantity) * widget_price AS vitrin_ciro,
P.*
FROM
tbl_products P
LEFT JOIN tbl_order_items I
ON I.product_id = P.id
WHERE
P.publish_date BETWEEN DATE_SUB( CURDATE( ) , INTERVAL 3 MONTH )
AND DATE_SUB( CURDATE( ) , INTERVAL 0 MONTH )
GROUP BY I.from_widget,
I.product_id
ORDER BY publish_date DESC ;
You could also make the query a nested one, if you don't like using SUM(quantity) many times:
SELECT
sum_quantity * buy_price AS ciro,
sum_quantity * list_price AS liste_ciro,
sum_quantity * widget_price AS vitrin_ciro,
tmp.*
FROM
( SELECT
SUM(I.quantity) AS sum_quantity,
I.from_widget,
COUNT(from_widget) AS order_count,
buy_price,
list_price,
widget_price,
P.*
FROM
tbl_products P
LEFT JOIN tbl_order_items I
ON I.product_id = P.id
WHERE
P.publish_date BETWEEN DATE_SUB( CURDATE( ) , INTERVAL 3 MONTH )
AND DATE_SUB( CURDATE( ) , INTERVAL 0 MONTH )
GROUP BY I.from_widget,
I.product_id
) AS tmp
ORDER BY publish_date DESC ;