I'm trying to see if I have some unused SIP numbers, so I have a list of numbers in the table tmp_numbers
0203XXXXX00
0203XXXXX01
0203XXXXX02
0203XXXXX03
...
The query I use is:
SELECT
n.number,
COUNT(c.did) AS count
FROM tmp_numbers n
LEFT JOIN cdr c
ON n.number = c.did
WHERE c.calldate >= '2017-01-01'
GROUP BY n.number
ORDER BY n.number
I get results from the above query, but it omits numbers it can't match on c.did.
I was under the impression that a LEFT JOIN would match/display everything on left table (tmp_numbers), regardless if there is a value on the right side (so it will show NULL?)
What am I missing here?
Put the where condition in the left join. Otherwise it turns implicitly into an inner join because conditions in the where clause filter on all data and if calldate is NULL then the condition is FALSE
LEFT JOIN cdr c ON n.number = c.did
AND c.calldate >= '2017-01-01'
You are querying on a column from the JOINED table which maybe null if there is no corresponding entry, so change the WHERE condition from:
WHERE c.calldate >= '2017-01-01'
to
WHERE c.calldate >= '2017-01-01' OR c.did IS NULL
Related
I have two table called tbl_calendar and tbl_affiliates_link_history, tbl_calendar I am using for fill missing dates in result.
If I use query like below its work fine
SELECT dates as date,COUNT(a.id)AS total_visits FROM tbl_calendar as c LEFT JOIN tbl_affiliates_link_history as a ON c.dates = DATE(a.link_visit_time) WHERE c.dates > '2022-02-01' AND c.dates < '2022-02-13' GROUP BY c.dates
and giving me result like below
But if I add one additional where condition in my query called a.affiliate_id='wilson'
It's giving me only one result instead of full result like first image
My second query is like this
SELECT dates as date,COUNT(a.id)AS total_visits FROM tbl_calendar as c LEFT JOIN tbl_affiliates_link_history as a ON c.dates = DATE(a.link_visit_time) WHERE c.dates > '2022-02-01' AND c.dates < '2022-02-13'AND a.affiliate_id='wilson' GROUP BY c.dates
According to the LEFT JOIN properties, if the record doesn't join with another record into the joining table, all fields of the logical table created with the join are NULL.
This means if you search anything on the joined table on NULL field the search automatically excludes the NULL fields and at this point you are using the LEFT JOIN as an INNER JOIN.
To solve this, you need to add OR field IS NULL to the WHERE condition to keep the NULL results. The second query should be:
SELECT dates as date, COUNT(a.id) AS total_visits
FROM tbl_calendar as c
LEFT JOIN tbl_affiliates_link_history as a ON c.dates = DATE(a.link_visit_time)
WHERE c.dates > '2022-02-01' AND c.dates < '2022-02-13' AND
(a.affiliate_id='wilson' OR a.affiliate_id IS NULL)
GROUP BY c.dates
I have a requirement to get sum, avg, count values as 0 following institution_name when lr.proccessed_on date is not matched with the input date. how can I achieve that in the following query
SELECT bd.id as institutionId,
bd.institution_name as institution,
count(lr.id) as numberOfTransaction,
sum(lr.amount) as totalTransactionAmount,
avg(lr.amount) as averageTransactionAmount,
sum(lr.processing_fee) as totalProcessingFee
from daily_transaction lr
join
(
select s.id
from status s
where s.name not in (:statusName)) s on
lr.customer_status = s.id
join account sa on
lr.account = sa.id
join branch b on
sa.branch = b.id
right join institution_details bd on
b.institution = bd.id
join status s2 on
bd.status = s2.id
where (:institutionIdParam is null
or bd.id = :institutionIdParam)
and (:instutionStatus is null
or s2.description = :instutionStatus)
and (:fromDate is null
and :toDate is null
or cast(lr.processed_on as date) <= :toDate
and cast(lr.processed_on as date) >= :fromDate)
group by bd.id , bd.institution_name
order by bd.institution_name asc;
The purpose of using RIGHT JOIN to institution_details seems to be that you want all institutions listed irrespective of their daily transactions. For those institutions where there are no daily transactions processed_on is treated as having NULL value (that is how the right join would behave), and a WHERE condition like yours would return false, and the institution_details are then filtered out.
You can overcome this by moving your parameter checking clause to the join condition, like so:
right join
institution_details bd on
b.institution = bd.id
and
((:fromDate is null and :toDate is null)
or
(cast(lr.processed_on as date) <= :toDate and cast(lr.processed_on as date) >= :fromDate))
and removing it from the WHERE clause.
Note the brackets I added to your expression; in the presence of both OR and AND operators we need to consider the operator precedence and order of evaluation, it would be incorrect (in my view) not to have these brackets. Even with these, you need to prevent a situation where only one (but not both) :fromDate and :toDate parameters is supplied.
i'm trying to get data for each month, if there is no data found for a particular month, I will put zero. I already created a calendar table so I can left join it, but I still can't get zero.
Here's my query
SELECT calendar.month, IFNULL(SUM(transaction_payment.total),0) AS total
FROM `transaction`
JOIN `transaction_payment` ON `transaction_payment`.`trans_id` =
`transaction`.`trans_id`
LEFT JOIN `calendar` ON MONTH(transaction.date_created) = calendar.month
WHERE`date_created` LIKE '2017%' ESCAPE '!'
GROUP BY calendar.month
ORDER BY `date_created` ASC
the value in my calendar tables are 1-12(Jan-Dec) int
Result should be something like this
month total
1 0
2 20
3 0
4 2
..
11 0
12 10
UPDATE
The problem seems to be the SUM function
SELECT c.month, COALESCE(t.trans_id, 0) AS total
FROM calendar c
LEFT JOIN transaction t ON month(t.date_created) = c.month AND year(t.date_created) = '2018'
LEFT JOIN transaction_payment tp ON tp.trans_id = t.trans_id
ORDER BY c.month ASC
I tried displaying the ID only and it's running well. but when I add back this function. I can only get months with values.
COALESCE(SUM(tp.total), 0);
This fixes the issues with your query:
SELECT c.month, COALESCE(SUM(tp.total), 0) AS total
FROM calendar c LEFT JOIN
transaction t
ON month(t.date_created) = month(c.month) AND
year(t.date_created) = '2017' LEFT JOIN
transaction_payment tp
ON tp.trans_id = t.trans_id
GROUP BY c.month
ORDER BY MIN(t.date_created) ASC;
This will only work if the "calendar" table has one row per month -- that seems odd, but that might be your data structure.
Note the changes:
Start with the calendar table, because those are the rows you want to keep.
Do not use LIKE with dates. MySQL has proper date functions. Use them.
The filtering conditions on all but the first table should be in the ON clause rather than the WHERE clause.
I prefer COALESCE() to IFNULL() because COALESCE() is ANSI standard.
You need to use right as per your query because you calendar table is present at right side
SELECT calendar.month, IFNULL(SUM(transaction_payment.total),0) AS total
FROM `transaction`
JOIN `transaction_payment` ON `transaction_payment`.`trans_id` =
`transaction`.`trans_id`
RIGHT JOIN `calendar` ON MONTH(transaction.date_created) = calendar.month
WHERE`date_created` LIKE '2017%' ESCAPE '!'
GROUP BY calendar.month
ORDER BY `date_created` ASC
I have somehow complicated query as follow:
SELECT w,e2.EntityID
FROM (SELECT EntityID,SUM(frequency) w
FROM omid.entity_epoch_data where EpochID in
( select id from epoch where startDateTime>='2013-11-01 00:00:00' and
startDateTime <= '2013-11-30 00:00:00')
GROUP BY EntityID) e1
RIGHT JOIN
entity e2 ON e1.EntityID = e2.EntityID order by w desc
And it works properly but as soon as I add another innerjoin:
SELECT w,e2.EntityID
FROM (SELECT EntityID,SUM(frequency) w
FROM omid.entity_epoch_data inner join omid.entity_dataitem_relation as e3 on(e1.EntityID = e3.EntityID)
where e3.dataitemtype=3 and EpochID in
( select id from epoch where startDateTime>='2013-11-01 00:00:00' and
startDateTime <= '2013-11-30 00:00:00')
GROUP BY EntityID) e1
RIGHT JOIN
entity e2 ON e1.EntityID = e2.EntityID order by w desc
I get the following error:
column 'EntityID' in the field set is ambiguous
Does anyone have an idea where my mistake is?
Update :
I have the right version as follow (it gives me exactly what I want)
SELECT ID,e2.EntityID,e2.Name,AVG(intensity),AVG(quality),SUM(frequency)
FROM omid.entity_epoch_data as e1
right JOIN entity AS e2 ON (e1.EntityID = e2.EntityID)
where EpochID in
( select id from epoch where startDateTime>='2013-11-01 00:00:00' and
startDateTime <= '2013-11-30 00:00:00') and e1.EntityID in
(SELECT entityid FROM omid.entity_dataitem_relation where dataitemtype=3)
group by e2.EntityID order by sum(frequency) desc;
But it takes time and I need to change the
(SELECT entityid FROM omid.entity_dataitem_relation where dataitemtype=3)
group by e2.EntityID order by sum(frequency) desc;
to innerjoin can anyone help me how to do that?
Image:
You have two problems.
First off, the syntax for that first INNER JOIN is not correct. You are conflating the INNER JOIN and ON parts of the statement. (At least, I think this is the case, unless you actually have "." characters in your table names are really want a cartesian result from this JOIN)>
Secondly, the second usage of EntityID (in that new INNER JOIN you added) could refer to the EntityID value from either the left or right side of the INNER JOIN -- that's what the "ambiguous column" in the error means.
Here is some SQL to get you started. It follows the selection logic you give in the comment, below. It names each table with an alias and ensures that each column specifies the table from which it should be drawn. I don't have an instance of MySQL handy to try it, but it should get you started.
SELECT E.EntityID, SUM(EED.Frequency)
FROM entity_epoch_data EED INNER JOIN entity_dataitem_relation EDR
ON EED.EntityID = EDR.EntityID WHERE EDR.entity_dataitemtype = 3
RIGHT OUTER JOIN entity E ON E.EntityID = EED.EntityID
GROUP BY E.EntityID
Maybe there are fields named EntityID in both tables - omid.entity_epoch_data and omid.entity_dataitem_relation ?
Your first query had only one take in the subquery to look for entityid, but the second query has two tables in the subquery.
Also, you are referencing table e1 inside a subquery before e1 is defined.
give the tables a specific alias name and that error will go away.. because you have two columns that are not distinguished, so when you try to use one it doesn't know which table to pull it from
I am having trouble getting a MySQL query to work for me. Here is the setup.
A customer has asked me to compile a report from some accounting data. He wants to select a date (and possibly other criteria) and have it return all of the following (an OR statement):
1.) All invoices that were inserted on or after that date
2.) All invoices regardless of their insert date that have corresponding payments in a separate table whose insert dates are on or after the selected date.
The first clause is basic, but I am having trouble pairing it with the second.
I have assembled a comparable set of test data in an SQL Fiddle. The query that I currently have is provided.
http://www.sqlfiddle.com/#!2/d8d9c/3/2
As noted in the comments of the fiddle, I am working with July 1, 2013 as my selected date. For the test to work, I need invoices 1 through 5 to appear, but not invoice #6.
Try this: http://www.sqlfiddle.com/#!2/d8d9c/9
Here are the summarized changes
I got rid of your GROUP BY. You did not have any aggregate functions. I used DISTINCT instead to eliminate duplicate records
I removed your implicit joins and put explicit joins in their place for readability. Then I changed them to LEFT JOINs. I am not sure what your data looks like but at a minimum, I would assume you need the payments LEFT JOINed if you want to select an invoice that has no payments.
This will probably get you the records you want, but those subselects in the SELECT clause may perform better as LEFT JOINs then using the SUM function
Here is the query
SELECT DISTINCT
a.abbr landowner,
CONCAT(f.ForestLabel, '-', l.serial, '-', l.revision) leasenumber,
i.iid,
FROM_UNIXTIME(i.dateadded,'%M %d, %Y') InvoiceDate,
(SELECT IFNULL(SUM(ch.amount), 0.00) n FROM test_charges ch WHERE ch.invoiceid = i.iid) totalBilled,
(SELECT SUM(p1.amount) n FROM test_payments p1 WHERE p1.invoiceid = i.iid AND p1.transtype = 'check' AND p1.status = 2) checks,
(SELECT SUM(p1.amount) n FROM test_payments p1 WHERE p1.invoiceid = i.iid AND p1.transtype = 'ach' AND p1.status = 2) ach,
CASE WHEN i.totalbilled < 0 THEN i.totalbilled * -1 ELSE 0.00 END credits,
CASE WHEN i.balance >= 0 THEN i.balance ELSE 0.00 END balance,
t.typelabel, g.groupname
FROM test_invoices i
LEFT JOIN test_contracts c
ON i.contractid = c.cid
LEFT JOIN test_leases l
ON c.leaseid = l.bid
LEFT JOIN test_forest f
ON l.forest = f.ForestID
LEFT JOIN test_leasetypes t
ON l.leasetype = t.tid
LEFT JOIN test_accounts a
ON l.account = a.aid
LEFT JOIN test_groups g
ON c.groupid = g.gid
LEFT JOIN test_payments p
ON p.invoiceid = i.iid
WHERE (i.dateadded >= #startdate) OR (p.dateadded >= #startdate)
Try this.
http://www.sqlfiddle.com/#!2/d8d9c/11/2
TL;DR:
… AND (i.dateadded > #startdate
OR EXISTS (
SELECT * FROM test_payments
WHERE test_payments.invoiceid = i.iid
AND test_payments.dateadded >= #startdate))