I have one table like this:
a. tbl_cdr
b. tbl_wo_notification_contacts
What I want was count all from tbl_wo_notification_contacts and tbl_cdr. Here is my query.
SELECT SUBSTRING(n.last_attempt,1,10) AS DATE,
SUM(IF(n.STATUS=1, 1,0)) AS 'Success',
SUM(IF(n.STATUS=2, 1,0)) AS 'Failed',
COUNT(*) AS 'TotalCalls'
FROM tbl_wo_notification_contacts n
WHERE n.last_attempt >= '2019-05-01' AND n.last_attempt <= '2019-07-01'
GROUP BY SUBSTRING(n.last_attempt,1,10);
The problem is I want to add new column called 'Total Duration' where it counts all from tbl_cdr based on the query condition.
Group tbl_cdr by ContactsID to get the counts.
SELECT SUBSTRING(n.last_attempt,1,10) AS DATE,
SUM(IF(n.STATUS=1, 1,0)) AS 'Success',
SUM(IF(n.STATUS=2, 1,0)) AS 'Failed',
COUNT(*) AS 'TotalCalls',
IFNULL(c.TotalDuration, 0) AS TotalDuration
FROM tbl_wo_notification_contacts n
LEFT JOIN (
SELECT ContactID, COUNT(*) AS TotalDuration
FROM tbl_cdr
GROUP BY ContactID) AS c ON c.ContactID = n.id
WHERE n.last_attempt >= '2019-05-01' AND n.last_attempt <= '2019-07-01'
GROUP BY SUBSTRING(n.last_attempt,1,10);
Related
So currently I have 2 tables called listings and logs table. The listings table holds a products reference number and it's current status. So suppose if it's status was Publish currently and it's sold, the status updates to Sold. Here the refno. in this table is unique since the status can change for 1 product.
Now I have another table called Logs table, this table records all the status changes that have happened for a particular product(referenced by refno) in a particular timeframe. Suppose the Product with refno. 5 was Publish on 1st October and Sold on 2nd October, The logs table will display as:
Refno
status_from
status_to
logtime
5
Stock
Publish
2021-10-01
5
Publish
Sold
2021-10-02
This is how my tables currently look like:
Listings table:('D'=>'Draft','N'=>'Action','Y'=>'Publish')
Logs Table which I'm getting using the following statement:
SELECT refno, logtime, status_from, status_to FROM (
SELECT refno, logtime, status_from, status_to, ROW_NUMBER() OVER(PARTITION BY refno ORDER BY logtime DESC)
AS RN FROM crm_logs WHERE logtime < '2021-10-12 00:00:00' ) r
WHERE r.RN = 1 UNION SELECT refno, logtime, status_from, status_to
FROM crm_logs WHERE logtime <= '2021-10-12 00:00:00' AND logtime >= '2015-10-02 00:00:00'
ORDER BY `refno` ASC
The logs table makes a new record every status change made and passes the current timestamp as the logtime, and the listings table changes/updates the status and updates its update_date. Now to get the total listings as of today I'm using the following statement:
SELECT SUM(status_to = 'D') AS draft, SUM(status_to = 'N') AS action, SUM(status_to = 'Y') AS publish FROM `crm_listings`
And this returns all the count data for status as of the current day.
Now this is where it gets confusing for me. So suppose today the count under action is 10 and tomorrow it'll be 15, and I want to retrieve the total that was present yesterday(10). So for this what I would've to do is take todays total(15) and subtract all the places where a product was changed to draft in between yesterday and today(Total count today in listing table - count(*) where status_to='Action' from logs table). Or vice versa, if yesterday it was 10 under action and today it is 5, it should add the values from the status_from column in logs table
Note: Refno isn't unique in my logs table since a product with the same refno can be marked as publish 1 day and unpublish another, but it is unique in my listings table.
Link to dbfiddle: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=01cb3ccfda09f6ddbbbaf02ec92ca894
I am sure it can be simplifed or better. But its my query and logic :
I found status_changes per refno's and calculated total changes from the desired day to present :
select status_logs, sum(cnt_status) to_add from (
SELECT
status_to as status_logs, -1*count(*) cnt_status
FROM logs lm
where
id = (select max(id) from logs l where l.refno = lm.refno) and
logtime >= '2021-10-01 00:00:00'
group by status_to
union all
SELECT
status_from, count(*) cnt_status_from
FROM logs lm
where
id = (select max(id) from logs l where l.refno = lm.refno) and
logtime >= '2021-10-01 00:00:00'
group by status_from ) total_changes
group by status_logs
I matched the keys between listings table and logs table by converting listings table keys :
select
case status
when 'D' THEN 'Draft'
when 'A' THEN 'Action'
when 'Y' THEN 'Publish'
when 'S' THEN 'Sold'
when 'N' THEN 'Let'
END status_l ,COUNT(*) c
from listings
group by status
I joined them and add the calculations to total sum of current data.
I had to use full outer join , so i have one left and one right join with the same subqueries.
Lastly I used distinct , since it will generate same result for each joined query and used ifnull to bring the other tables status to the other column .
select distinct IFNULL(status_l, status_logs) status, counts_at_2021_10_01
from (select l.*,
logs.*,
l.c + ifnull(logs.to_add, 0) counts_at_2021_10_01
from (select case status
when 'D' THEN
'Draft'
when 'A' THEN
'Action'
when 'Y' THEN
'Publish'
when 'S' THEN
'Sold'
when 'N' THEN
'Let'
END status_l,
COUNT(*) c
from listings
group by status) l
left join (
select status_logs, sum(cnt_status) to_add
from (SELECT status_to as status_logs,
-1 * count(*) cnt_status
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_to
union all
SELECT status_from, count(*) cnt_status_from
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_from) total_changes
group by status_logs) logs
on logs.status_logs = l.status_l
union all
select l.*,
logs.*,
l.c + ifnull(logs.to_add, 0) counts_at_2021_05_01
from (select case status
when 'D' THEN
'Draft'
when 'A' THEN
'Action'
when 'Y' THEN
'Publish'
when 'S' THEN
'Sold'
when 'N' THEN
'Let'
END status_l,
COUNT(*) c
from listings
group by status) l
right join (
select status_logs, sum(cnt_status) to_add
from (SELECT status_to as status_logs,
-1 * count(*) cnt_status
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_to
union all
SELECT status_from, count(*) cnt_status_from
FROM logs lm
where id = (select max(id)
from logs l
where l.refno = lm.refno)
and logtime >= '2021-10-01 00:00:00'
group by status_from) total_changes
group by status_logs) logs
on logs.status_logs = l.status_l) l
How to sum over values by month from two table?
I have two table:
1)costs_1
-id
-total
-updated_at(timestamp)
2)costs_2
-id
-total_1
-updated_at_1(timestamp)
The result table need have next columns:
-total
-total_1
-month
For example, if I have one table I do next query:
SELECT SUM(total), MONTH(updated_at), YEAR(updated_at) FROM product_sale GROUP BY MONTH(updated_at), YEAR(updated_at) ORDER by MONTH(updated_at)
I believe you want something like this.
SELECT t1.y year,
t1.m month,
t1.total,
t2.total
FROM
(
SELECT YEAR(updated_at) y,
MONTH(updated_at) m,
SUM(total) total
FROM costs_1
GROUP BY YEAR(updated_at), MONTH(updated_at)
) t1
JOIN
(
SELECT YEAR(updated_at_1) y,
MONTH(updated_at_1) m,
SUM(total_1) total
FROM costs_2
GROUP BY YEAR(updated_at_1), MONTH(updated_at_1)
) t2 ON t1.y = t2.y and t1.m = t2.m
However, in this solution, you will miss a month if costs_1 or costs_2 does not have any record with the month. If you want FULL JOIN you have to emulate it in mysql using two OUTER JOINS like this:
SELECT t1.y year,
t1.m month,
COALESCE(t1.total, 0),
COALESCE(t2.total, 0)
FROM
(
SELECT YEAR(updated_at) y,
MONTH(updated_at) m,
SUM(total) total
FROM costs_1
GROUP BY YEAR(updated_at), MONTH(updated_at)
) t1
LEFT JOIN
(
SELECT YEAR(updated_at_1) y,
MONTH(updated_at_1) m,
SUM(total_1) total
FROM costs_2
GROUP BY YEAR(updated_at_1), MONTH(updated_at_1)
) t2 ON t1.y = t2.y and t1.m = t2.m
UNION
SELECT t2.y year,
t2.m month,
COALESCE(t1.total, 0),
COALESCE(t2.total, 0)
FROM
(
SELECT YEAR(updated_at) y,
MONTH(updated_at) m,
SUM(total) total
FROM costs_1
GROUP BY YEAR(updated_at), MONTH(updated_at)
) t1
RIGHT JOIN
(
SELECT YEAR(updated_at_1) y,
MONTH(updated_at_1) m,
SUM(total_1) total
FROM costs_2
GROUP BY YEAR(updated_at_1), MONTH(updated_at_1)
) t2 ON t1.y = t2.y and t1.m = t2.m
Try this:
SELECT total, total_1, MONTHNAME(costs_1.updated_at) from costs_1 INNER JOIN costs_2
ON
MONTH(costs_1.updated_at)=MONTH(costs_2.updated_at)
I'm trying to select if a user rating (user.rating) is greater then 6 or if the user has more then 100 transactions (transaction table count). Basically count how many transactions the user has then where (transaction count >= 100 OR user rating >= 6).
SELECT *
FROM `user`
JOIN (SELECT COUNT(*)
FROM transaction
WHERE transaction.user_id=user.id
AND type='L'
AND status='S') AS tcount
WHERE (user.rating >= '6' OR tcount >= '100')
Just another possible answer. I've created simplified schemas to test it, please try it and let me know the result.
SELECT *
FROM user
WHERE user.rating >= 6 OR (SELECT COUNT(*) FROM transaction WHERE user_id = user.id and type = 'L' and status = 'S') >= 100;
Use an alias on COUNT(*)
SELECT *
FROM `user`
JOIN (SELECT user_id, COUNT(*) cnt
FROM transaction
WHERE type='L'
AND status='S'
GROUP BY user_id) AS tcount
ON user.id = tcount.user_id
WHERE (user.rating >= '6' OR tcount.cnt >= '100')
You can write that without the subquery, like this
SELECT u.id
FROM `user` u
JOIN `transaction` t
ON t.user_id=u.id
WHERE t.type = 'L' AND t.status = 'S'
GROUP BY u.id
HAVING sum(case when u.rating >= 6 then 1 end) > 0 OR count(*) >= 100
How Can I find those order numbers which does not have invoice number? I did following query and it's showing all the order which has invoice number.How can I get all the order numbers which does not have invoice number?
SELECT invoice_tbl.increment_id AS 'Sales_Invoice_Number', order_tbl.increment_id AS 'Sales Order Number'
FROM magentodb.sales_flat_invoice AS invoice_tbl
JOIN magentodb.sales_flat_order AS order_tbl
ON (order_tbl.entity_id = invoice_tbl.order_id)
WHERE order_tbl.created_at >= '2014-03-17'
AND order_tbl.created_at <= '2014-05-07'
You can use a NOT EXISTS clause.
SELECT order_tbl.increment_id AS 'Sales Order Number'
FROM magentodb.sales_flat_order AS order_tbl
WHERE order_tbl.created_at >= '2014-03-17'
AND order_tbl.created_at <= '2014-05-07'
AND NOT EXISTS (SELECT NULL FROM magentodb.sales_flat_invoices
WHERE order_tbl.entity_id = order_id)
a LEFT JOIN on sales_flat_invoice
with a where clause checking for null order_id could also do the trick.
Select order_tbl.increment_id AS 'Sales Order Number'
FROM magentodb.sales_flat_order AS order_tbl
WHERE order_tbl.increment_id NOT IN (select invoice_tbl.order_id
FROM magentodb.sales_flag_invoice AS invoice_tbl)
AND order_tbl.created_at >= '2014-03-17'
AND order_tbl.created_at <= '2014-05-07'
This will select all orders from the order_tbl that do not have an associated row in the invoice table, retaining your original filtering at the bottom of the query.
I want to combine three tables - date, lead and click - in a query.
The tables looks like this:
date:
|date|
lead:
id|time|commission
click:
id|time|commission
The table date is just storing dates and is used when getting dates with no click or lead.
So if we have the following data in the tables:
date:
2009-06-01
2009-06-02
2009-06-03
lead:
1|2009-06-01|400
2|2009-06-01|300
3|2009-06-03|350
click:
1|2009-06-01|1
2|2009-06-03|2
3|2009-06-03|2
4|2009-06-03|0
I would like to get date, number of click, commission generated by clicks (there are clicks that don't give commission), number of leads, commission generated by leads and total commission. So with the tables above I would like to get:
2009-06-01|1|1|2|700|701|
2009-06-02|0|0|0|0|0
2009-06-03|3|4|1|350|354|
I have tried with the following union:
SELECT
campaign_id,
commission_date,
SUM( click_commission ) AS click_commission,
click,
SUM( lead_commission ) AS lead_commission ,
lead,
SUM( total_commission ) as total_commission
FROM(
SELECT
click.campaign_id AS campaign_id,
DATE( click.time ) AS commission_date,
click.commission AS click_commission,
(SELECT count(click.id) from click GROUP BY date(click.time)) as click,
0 as lead_commission,
0 as lead,
click.commission AS total_commission
FROM click
UNION ALL
SELECT
lead.campaign_id AS campaign_id,
DATE( lead.time ) AS commission_date,
0 as click_commission,
0 as click,
lead.commission AS lead_commission,
lead.id as lead,
lead.commission AS total_commission
FROM lead
UNION ALL
SELECT
0 AS campaign_id,
date.date AS commission_date,
0 AS click_commission,
0 as click,
0 AS lead_commission,
0 as lead,
0 AS total_commission
FROM date
) AS foo
WHERE commission_date BETWEEN '2009-06-01' AND '2009-07-25'
GROUP BY commission_date
ORDER BY commission_date LIMIT 0, 10
But this does not work to count both the number of clicks and leads, the code above gives the right amount of clicks bot 0 on all leads. If I move the code around and put the select from the lead table I get the leads right bot 0 on all clicks. I have not been able to find a way to get both of the counts from the query.
So I tried a left-join instead:
SELECT
date.date as date,
count( DISTINCT click.id ) AS clicks,
sum(click.commission) AS click_commission,
count( lead.id ) AS leads,
sum(lead.commission) AS lead_commission
FROM date
LEFT JOIN click ON ( date.date = date( click.time ) )
LEFT JOIN lead ON ( date.date = date( lead.time ) )
GROUP BY date.date
LIMIT 0 , 30
The problem with this query is if there are more than one clicks or leads on a date it will return the expected value * 2. So on 2009-06-01 it will return 1400 instead on the expected 700 for lead commission.
So in the UNION I have problems with the count and in the left join it is the SUM that is not working.
I would really like to stick to the UNION if possible, but I haven't found a way to get both counts from it.
(This is a follow up to this earlier question, but since I didn't ask for the count in that I posted a new question.)
SELECT date,
COALESCE(lcomm, 0), COALESCE(lcnt, 0),
COALESCE(ccomm, 0), COALESCE(ccnt, 0),
COALESCE(ccomm, 0) + COALESCE(lcomm, 0),
COALESCE(ccnt, 0) + COALESCE(lcnt, 0)
LEFT JOIN
(
SELECT date, SUM(commission) AS lcomm, COUNT(*) AS lcnt
FROM leads
GROUP BY
date
) l
ON l.date = d.date
LEFT JOIN
(
SELECT date, SUM(commission) AS ccomm, COUNT(*) AS ccnt
FROM clicks
GROUP BY
date
) с
ON c.date = d.date
FROM date d
The code that I used, built from the suggestion from Quassnoi:
SELECT date,
COALESCE(ccomm, 0) AS click_commission, COALESCE(ccnt, 0) AS click_count,
COALESCE(lcomm, 0) AS lead_commision, COALESCE(lcnt, 0) AS lead_count,
COALESCE(ccomm, 0) + COALESCE(lcomm, 0) as total_commission
FROM date d
LEFT JOIN
(
SELECT DATE(time) AS lead_date, SUM(commission) AS lcomm, COUNT(*) AS lcnt
FROM lead
GROUP BY
lead_date
) l
ON lead_date = date
LEFT JOIN
(
SELECT DATE(time) AS click_date, SUM(commission) AS ccomm, COUNT(*) AS ccnt
FROM click
GROUP BY
click_date
) с
ON click_date = date