Here is my query. I am trying to join a table with a defined table. But the problem is when we are trying Left join it effects same like inner join.
SELECT A.*,B.*,
(CASE WHEN A.preday != '' THEN 'A' ELSE 'P' END) AS PreStat
FROM (
SELECT '2016-05-04' AS preday
UNION
SELECT '2016-05-03'
UNION
SELECT '2016-05-02'
) AS A
LEFT JOIN `student_attendence` AS B ON B.date = A.preday
WHERE student_id='1' ;
For example in my right table doesn't contain a date field with value '2016-05-02' , But when we are trying left join it should come with NULL values ..but it won't come.
my right join table structure is
Please help me to solve it.
Think about this for a second. Student_ID only exists on student_Attendence table (for these 2 tables anway). A student may not have a record for that given day (must be the case if you're not getting 02 in the results; at least for student 1) If you want all days from your derived union table; then you need to filter students_ID before the join occurs so the unmatched day for student 1 record is preserved from the left join
SELECT A.*,B.*, (CASE WHEN A.preday != '' THEN 'A' ELSE 'P' END) AS PreStat
FROM (SELECT '2016-05-04' AS preday
UNION SELECT '2016-05-03'
UNION SELECT '2016-05-02') AS A
LEFT JOIN `student_attendence` AS B
ON B.date = A.preday
and student_id='1' ;
Student_Attendance for Student_ID 1 would be...
ID Date
1 2016-05-05
1 2016-05-04
1 2016-05-03
1 2016-05-01
So the left join would result in ...
Preday ID Date
2016-05-04 1 2016-05-04
2016-05-03 1 2016-05-03
2016-05-02
and when you apply the where clause ... since 2016-05-02 has no entry for Student 1, it gets eliminated..
Preday ID Date
2016-05-04 1 2016-05-04
2016-05-03 1 2016-05-03
But if you move the where clause to the join... you get this as the filter is applied before the join, thus retaining the 02 date.
Preday ID Date
2016-05-04 1 2016-05-04
2016-05-03 1 2016-05-03
2016-05-02
the reason because of the logical query processing of the query as the first clause to be executed is the from clause then where > grouping > having > select > order by
so when you execute your own query the first clause to be executed is the from which returned '2016-05-02' with null as expected with the left join
but the where clause after that filters the result set and remove it because the null is unknown (it isn't a value, it stands for missing value)
so you can do something like replacing the where clause with and operator.
Related
Im creating a query that select two tables and create a total variable by count a field in one table.
Example:
Table A:
ID | email
1 | test#test
2 | test2#test
3 | test3#test
Table B
ID | email_id | username_id
1 | 1 | 11
2 | 1 | 22
3 | 2 | 33
My query:
select a.id, a.email, count(c.id) as total
from tableA a
left join tableC c on c.email_id = a.id AND total <= 5
group by a.email LIMIT 1
Output:
Unknown column 'total' in 'on clause
I need to select the first "a.id" that has total <= 5. How can I do it?
Logically Select is processed after the Where clause so you cannot use Alias name in same Where clause.
Use HAVING clause
select a.id, a.email, count(c.id) as total
from tableA a
left join tableC c on c.email_id = a.id
group by a.email
Having count(c.id) <= 5
LIMIT 1
I think Mysql allows you do this as well
Having total <= 5
Try HAVING Count(c.id) <= 5
Just to make this a bit clearer, since the correct answer has already been provided - You don't have to use the HAVING clause, and the HAVING clause is not always the solution for this problem.
The HAVING clause is usually used to place filters on aggregated columns (sum,count,max,min etc..) , but when you have a calculated column (colA + colB as calc_column for example) , then another approach , which should work here as well is to wrap the query with another select, and then the new column will be available on the WHERE :
SELECT *
FROM (The query here ) s
WHERE s.total <= 5
For example I have a table A and B with the following data:
A:
user_name date1 count1 count2
X 15 1 1
X 30 1 3
Y 04 1 3
B:
user_name date1 count3 count4 status
X 15 11 1 Y
X 30 13 3 N
Y 04 16 3 NA
How to join these 2 tables for each feedname with max date.
I need the output like these:
username date1 count1 count4 status
X 30 1 3 N
like these way.
Can anyone plz help in these situation.
Since according to your comment every combination (user_name, date1) exists in both tables, you can use e.g.
select a.*, b.count3, b.count4, b.status
from tableA as a
join tableB as b
on a.user_name = b.user_name and
a.date1 = b.date1
where not exists
(select 1 from tableA as a1
where a1.user_name = a.user_name
and a1.date1 > a.date1);
You want to have an index on (user_name, date1) to speed it up.
As a side note: If every entry in tableA has exactly 1 entry in tableB and vice-versa (it's not clear from your description if that is the case, but it looks like it), and thus (user_name, date1) would be a primary key in both tables, you absolutely should add the columns count3, count4 and status to tableA and get rid of tableB. You can still use the above code (without join) to find only the max entry per user.
I have the following tables, for example:
invoices
ID Name
1 A
2 B
3 C
4 D
5 E
transactions
ID Invoice_ID User_ID
1 1 10
2 1 10
3 1 10
4 2 30
5 3 20
6 3 40
7 2 30
8 2 30
9 4 40
10 3 50
Now I want to make a select that will pull the invoices and the user_id from the related transactions, but of course if I do that I won't get all the ids, since they may be distinct but there will be only one column for that. What I want to do is that if there are distinct User_ids, I will display a pre-defined text in the column instead of the actual result.
select invoices.id, invoices.name, transactions.user_id(if there are distinct user_ids -> return null)
from invoices
left join transactions on invoices.id = transactions.invoice_id
and then this would be the result
ID Name User_ID
1 A 10
2 B 30
3 C null
4 D 40
5 E null
Is this possible?
You can do the following :
select
invoices.id,
invoices.name,
IF (
(SELECT COUNT(DISTINCT user_id) FROM transactions WHERE transactions.invoice_id = invoices.id) = 1,
(SELECT MAX(user_id) FROM transactions WHERE transactions.invoice_id = invoices.id),
null
) AS user_id
from invoices
Or, alternatively, you can use the GROUP_CONCAT function to output a comma-separated list of users for each invoice. It is not exactly what you asked, but maybe in fact it will be more useful :
select
invoices.id,
invoices.name,
GROUP_CONCAT(DISTINCT transactions.user_id SEPARATOR ',') AS user_ids
from invoices
left join transactions on invoices.id = transactions.invoice_id
group by invoices.id
Try somethingh like:
select i.id, i.name, t.user_id
from invoices i left join
(
select invoice_ID, User_ID
from transactions
group by invoice_ID
having count(invoice_ID)=1
) t on i.id=t.invoice_id
SQL fiddle
You could list all the transactions that have multiple user ids, like this:
select invoices.id, invoices.name, null
from invoices
left join transactions on invoices.id = transactions.invoice_id having count(distinct transactions.user_id) > 1
Also, I think this CASE might suit your needs here:
select invoices.id, invoices.name,
case when count(distinct transactions.user_id) > 1 then null else transactions.user_id end
from invoices
left join transactions on invoices.id = transactions.invoice_id
group by invoices.id
although, I'm not sure this is syntactically correct
I have two similar tables that I need to locate any records that exist in one table but not the other, but the only value I have to find these records have multiple duplicate values.
Table 1:
TId Date TYPE AMOUNT
1 2014-02-01 23 25.34
2 2014-02-01 23 46.95
3 2014-02-01 23 46.95
4 2014-02-01 23 25.34
5 2014-02-01 23 21.01
Table 2:
TId Date TYPE AMOUNT
7 2014-02-01 23 25.34
8 2014-02-01 23 46.95
9 2014-02-01 23 21.01
I need to query the two tables to locate records 3 and 4 from table 1. The issue is I'm finding a match in records 7 and 8 in table 2. I've used 'NOT EXISTS' and 'JOIN' but can't seem to get the results I'm looking for.
I am not 100% sure on what you want to find, but it sounds like you want the records on table 1 that are not on table 2, based on the date, type and amount.
If so a left join and checking for NULL on a field is probably the best way to do it:-
SELECT table1.*
FROM table1
LEFT OUTER JOIN table2
ON table1.Date = table2.Date
AND table1.Type = table2.Type
AND table1.Amount = table2.Amount
WHERE table2.TId IS NULL
Possibly like this (depending on your exact requirements). This should get all the records from table1, and join that against a record where the date, type and amount match AND the tid is the first for that record. Then joined against table2. Records put out if there is no match on table2, or there is a match but the records on table1 is not the first one that would match.
The does only work if there are no duplicates on table2.
SELECT table1.*
FROM table1
LEFT OUTER JOIN
(
SELECT Date, TYPE, AMOUNT, MIN(TId) AS TId
FROM table1
) t11
ON table1.Date = t11.Date
AND table1.Type = t11.Type
AND table1.Amount = t11.Amount
AND table1.TId = t11.TId
LEFT OUTER JOIN table2
ON table1.Date = table2.Date
AND table1.Type = table2.Type
AND table1.Amount = table2.Amount
WHERE (t11.TId IS NULL
AND table2.TId IS NOT NULL)
OR table2.TId IS NULL
Hi there m trying to calculate the row count for same value,
id,value
1 | a
2 | b
3 | c
4 | d
5 | e
and my query is
select value, count(*) as Count from mytable where id in('4','2','4','1','4') group by value having count(*) > 1
for which my expected output will be,
value,Count
d | 3
b | 1
a | 1
Thanks, any help will be appreciated
Try that:
SELECT value, count(value) AS Count
FROM mytable m
WHERE value = m.value
GROUP BY value
SELECT t.id, t.value, COUNT(t.id)
FROM
test t
JOIN
( SELECT 1 AS id
UNION ALL SELECT 3
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 1
UNION ALL SELECT 1 ) AS tmp
ON t.id = tmp.id
GROUP BY t.id
Sample on sqlfiddle.com
See also: Force MySQL to return duplicates from WHERE IN clause without using JOIN/UNION?
Of course, your IN parameter will be dynamic, and thus you will have to generate the corresponding SQL statement for the tmp table.
That's the SQL-only way to do it. Another possibility is to have the query like you have it in your question and afterwards programmatically associate the rows to the count passed to the IN parameter.