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
Related
Let's say I have two tables
Table a
some_ID
1
2
3
4
Table b
some_ID
1
2
1
4
Now what I would like to receive is a table like
id amount
1 | 2
2 | 1
I tried with a following query:
SELECT COUNT(a.some_id) as id
FROM Table_a
INNER JOIN Table_b
ON Table_a.some_id = Table.b.some_id
but that only returned how many id rows there are in both tables.
Any help?
Do the grouping on table_b and then join that result set on table_a
SELECT b.* FROM
(
SELECT id, COUNT(*) AS Cnt
FROM Table_b
GROUP BY id
) b
INNER JOIN Table_a a ON a.id = b.id
SQLFiddle
If you want the zero counts:
SELECT a.some_id AS id, count(b.some_id) as amount
FROM a LEFT JOIN b ON a.some_id = b.some_id
GROUP BY a.some_id
Result:
id | amount
1 | 2
2 | 1
3 | 0
4 | 1
If not:
SELECT a.some_id AS id, count(*) as amount
FROM a INNER JOIN b ON a.some_id = b.some_id
GROUP BY a.some_id
Result:
id | amount
1 | 2
2 | 1
4 | 1
The difference is the join type. Once left outer join. Then inner join. Note that in the first case it is important to count with count(b.some_id). With count(*) the rows with missing b entries would be counted as 1. count(*) counts the rows. count(expression) counts the non-null values.
If I understand correctly, you want a histogram of histograms:
select cnt, count(*) as num_ids
from (select id, count(*) as cnt
from b
group by id
) b
group by cnt;
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.
anyone knows how its possible that queries:
SELECT a.id, b.id FROM a CROSS JOIN b and
SELECT a.id, b.id FROM b CROSS JOIN a
return the same result? In both cases records from less numerous table are assigned to more numerous table. I want to get something like this:
`| a.id | b.id |
-------+-----+
1 | q |
1 | w |
1 | e |
1 | r |
2 | q |
2 | w |
2 | e |
2 | r |
`
but im getting result like this:
`| a.id | b.id |
-------+-----+
1 | q |
2 | q |
1 | w |
2 | w |
1 | e |
2 | e |
1 | r |
2 | r |
`
It's kinda strange that mysql automatically choose order of cross joined tabled depending of their numerous. I know i can use ORDER BY but i need to do this by CROSS JOIN.
There is more complex problem, i want to get 10 records per a.id. I saw solution for that: row counting with IF condition in SELECT clause. That row counting require rows sorted by a.id in raw result (without order by). Is there any other solution to do that?
NO, without a ORDER BY there is no specific order guaranteed. if you want a specific order to be maintained always then use order by clause. So in your case do like
SELECT a.id, b.id FROM a CROSS JOIN b
ORDER BY a.id;
i want to get 10 records per a.id.
Use a LIMIT clause along with ORDER BY like below; but without using ORDER BY you can never assure any order. Check MySQL documentation for more information.
SELECT a.id, b.id FROM a CROSS JOIN b
ORDER BY a.id
LIMIT 0,10;
First, the two results that you show are the same. With no order by clause, SQL results sets, like SQL tables, represent unordered sets. The ordering is immaterial. So, the sets are the same.
Your problem is quite different from this. If you want ten rows from table b for each record in table a, then you need to enumerate them. Typically, the fastest way in MySQL is to use a subquery and variables:
select a.*, b.*
from a left join
(select b.*,
(#rn := if(#a = b.aid, #rn + 1,
if(#a := b.aid, 1, 1)
)
) as seqnum
from b cross join
(select #rn := 0, #a := 0) params
order by b.aid
) b
where seqnum <= 10
order by a.aid;
There are other solutions, but this is undoubtedly the best.
Is it possible to select the next lower number from a table without using limit.
Eg: If my table had 10, 3, 2 , 1 I'm trying to select * from table where col > 10.
The result I'm expecting is 3. I know I can use limit 1, but can it be done without that?
Try
SELECT MAX(no) no
FROM table1
WHERE no < 10
Output:
| NO |
------
| 3 |
SQLFiddle
Try this query
SELECT
*
FROM
(SELECT
#rid:=#rid+1 as rId,
a.*
FROM
tbl a
JOIN
(SELECT #rid:=0) b
ORDER BY
id DESC)tmp
WHERE rId=2;
SQL FIDDLE:
| RID | ID | TYPE | DETAILS |
------------------------------------
| 2 | 28 | Twitter | #sqlfiddle5 |
Another approach
select a.* from supportContacts a inner join
(select max(id) as id
from supportContacts
where
id in (select id from supportContacts where id not in
(select max(id) from supportContacts)))b
on a.id=b.id
SQL FIDDLE:
| ID | TYPE | DETAILS |
------------------------------
| 28 | Twitter | #sqlfiddle5 |
Alternatively, this query will always get the second highest number based on the inner where clause.
SELECT *
FROM
(
SELECT t.col,
(
SELECT COUNT(distinct t2.col)
FROM tableName t2
WHERE t2.col >= t.col
) as rank
FROM tablename t
WHERE col <= 10
) xx
WHERE rank = 2 -- <<== means second highest
SQLFiddle Demo
SQLFiddle Demo (supports duplicate values)
If you want to get next lower number from table
you can get it with this query:
SELECT distinct col FROM table1 a
WHERE 2 = (SELECT count(DISTINCT(b.col)) FROM table1 b WHERE a.col >= b.col);
later again if you want to get third lower number you can just pass 3 in place of 2 in where clause
again if you want to get second higher number, just change the condition of where clause in inner query with
a.col <= b.col
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.