I tried to excute an inner select query as followed:
SET #rank = 0;
SELECT #rank := #rank + 1 AS id,
(SELECT a.id, COUNT(*) FROM table_A a GROUP BY a.id) AS count
FROM table_e e, table_p p
WHERE id= '100';
but I got the error as belowed
“Operand should contain 1 column(s)”
I tested the sub-query on its own and it worked fine. What is wrong with it?
EDIT
In fact my count sub query looks like this:
(SELECT COUNT(*) FROM table_e e, table_p p a GROUP BY p.id) AS count
I´m trying to count how many items in table_e exist in table_p.
Problem is following part of your query, which selects two columns for one alias:
(SELECT a.id, COUNT(*) FROM table_A a GROUP BY a.id) AS count
Bases to the name of the alias, selecting a.id is probably not needed.
Related
How can I select from in other select in MYSQL query?
Something like this
SET #row_number = 0;
SELECT a.num FROM
(SELECT
(#row_number:=#row_number + 1) AS num, id
FROM
main) as a where a.id=6
I want to know the number of records where id=6 if it's the first row, second row or third one
If your query has the filter where a.id = 6, then the row with id = 6 will always be the first row of the result set.
I am interpreting your question to mean: "if I sorted by id ascending, what row number is the row with id = 6 going to be on". If so, you can use a simple aggregation:
SELECT COUNT(*)
FROM main m
WHERE m.id <= 6;
Your query seems inspired by enumerating all the rows. You could do this version as well:
select m.*
from (select m.*, (#rn := #rn + 1) as rn
from main m cross join
(select #rn := 0) params
order by id
) m
where id = 6;
The first version should be more efficient, particularly with an index on id.
Let's say I have a table films(film, category).
I want to find the category with the most films. How do I do that without using LIMIT?
I suppose I could do something like this:
SELECT category
FROM
(SELECT category, COUNT(*) AS num
FROM films
GROUP BY category) AS T1
WHERE num =
(SELECT MAX(num)
FROM
(SELECT category, COUNT(*) AS num
FROM films
GROUP BY category) AS T2)
But is there a more elegant way of doing that? Preferably one where I don't have to write the same subquery multiple times?
Thanks!
(And if you're wondering why I can't use LIMIT, it's for homework)
you could do it using a variable to create a row number:
SELECT category
FROM
(
SELECT
category
COUNT(*) as NumOfFiles
,(#rn:= #rn + 1) as RowNumber
FROM
Films f
CROSS JOIN (SELECT #rn:=0) vars
GROUP BY
category
ORDER BY
COUNT(*) DESC
) t
WHERE
t.RowNumber = 1
I have two tables - PRODUCT, ACTIVITY. Each product can have multiple activity (1:n). Each activity has an (INT) action column. I need to query all the products and the SUM(product.action) of the 10 most recent activities.
My first attempt was to use a sub-query:
select p.*, (select sum(a.action) from activity a
where a.product_id = p.product_id
order by a.timestamp desc limit 10) recent
from product p
However, the result was incorrect. I realized that the sub-query wasn't using the LIMIT and was returning the SUM() of all ACTIVITY records matching the product_id.
My second attempt was to follow the advice here and wrap the sub-query in another select query:
select p.*, (select sum(temp.action) as recent
from (select a.action from activity a
where a.product_id = p.product_id
order by a.timestamp desc limit 10) temp)
from product p
However, I got the error message
Error Code: 1054. Unknown column 'p.product_id' in 'where clause'. I found a related question here and realized that MYSQL doesn't support alias on 2nd level nesting. I didn't quite follow the answer for that question.
I also tried an outer join
select p.*, sum(temp.action) as recent
from product p
left join
(select a.product_id, a.action from activity a
where a.product_id = p.product_id
order by a.timestamp desc limit 10) temp
on p.product_id= temp.product_id
Again, I ran into the same issues:
The LIMIT is not enforced
The alias is not recognized
How do I fix this?
1- Get distinct products from your product table
2- Get the ten most recent activities for each product
3- Get sums from (2)
4- Join
Take a look at Using LIMIT within GROUP BY to get N results per group?. It sounds similar to what you need for (2).
EDIT
I modified the query slightly and tested it on a small dataset. The previous version did not work because the where clause was in the wrong place. See below.
select t.product_id, sum(t.action) from
(
select product_id, action, timestamp,
#row_num := if(#prev = product_id, #row_num + 1, 1) as row_num, #prev := product_id
from activity
join (select #prev := null, #row_num := 0) as vars
order by product_id, timestamp desc
) as t
where t.row_num <= 10
group by t.product_id;
I have 3 tables A,B and C. In the stored procedure,I have used a query to get the result but i also want the total number of records i got from the above query.
Is this possible. I tried using something like this
Select count(*)
from (
select A.Name,B.Address,C.grade
from A,B,C
where A.id=B.id
AND B.Tlno=C.tlno
)
But this is not working.
(1) stop using old-style x,y,z joins.
SELECT A.Name,B.Address,C.grade
FROM dbo.A
INNER JOIN dbo.B ON A.id = B.id
INNER JOIN dbo.C ON B.Tlno = C.tlno;
(2) you can add a count(*) over() to the entire resultset. This is kind of wasteful because it returns the count on every row:
SELECT A.Name, B.Address, C.grade, row_count = COUNT(*) OVER ()
FROM dbo.A
INNER JOIN dbo.B ON A.id = B.id
INNER JOIN dbo.C ON B.Tlno = C.tlno;
You can use a windowing function:
select A.Name,
B.Address,
C.grade,
count(*) over () as total_count
from A,B,C
where A.id=B.id
AND B.Tlno=C.tlno
this will return the total count in each and every row though (but it will be the same number for all rows).
Alternative would be to use the ##rowcount keyword:
SELECT A.Name, B.Address, C.grade, ##rowcount
FROM dbo.A
INNER JOIN dbo.B ON A.id = B.id
INNER JOIN dbo.C ON B.Tlno = C.tlno;
Same result as the windowing function though, so you get the total count on each row. I'm curious if there is a performance difference between the two... (don't have SHOWPLAN permission at my current client unfortunately)
use a table variable as below
declare #num table (accname varchar(200),subnet varchar(200))
insert into #num(accname,subnet) Select a.accountname,s.subnet from tbl_accounts a,tbl_accountsubnet s where a.accountid=s.accountid
select COUNT(*) from #num;
i have table as
id----name----roll-----class
1----ram-------1-----2
2----shyam-----2-----3
3----ram-------1-----3
4----shyam-----2-----3
5----ram-------1-----2
6----hari------1-----5
i need to find the the duplicate row only that have common name, roll, class. so the expected result for me is.
id----name----roll-----class
1----ram-------1-------2
2----shyam-----2-------3
4----shyam-----2-------3
5----ram-------1-------2
i tried to get from the query below but here only one field is supported. i need all three field common. Please do help me in this. thanks
SELECT *
FROM table
WHERE tablefield IN (
SELECT tablefield
FROM table
GROUP BY tablefield
HAVING (COUNT(tablefield ) > 1)
)
You can use count() over().
select id, name, roll, class
from (select id, name, roll, class,
count(*) over(partition by name, roll, class) as c
from YourTable) as T
where c > 1
order by id
https://data.stackexchange.com/stackoverflow/query/63720/duplicates
this will retun only the duplicate entry one time:
select t.id, t.name, t.roll, t.class
from table t
inner join table t1
on t.id<t1.id
and t.name=t1.name
and t.roll = t1.roll
and t.class=t1.class
this will return what you require:
select distinct t.id, t.name, t.roll, t.class
from table t
inner join table t1
on t.name=t1.name
and t.roll = t1.roll
and t.class=t1.class
I'd suggest something like this
SELECT A.* FROM
Table A LEFT OUTER JOIN Table B
ON A.Id <> B.Id AND A.Name = B.Name AND A.Roll = B.Roll AND A.Class = B.Class
WHERE B.Id IS NOT NULL
Something like that should work (I did not test though):
select a1.*
from table a1, a2
where (a1.id != a2.id)
and (a1.name == a2.name)
and (a1.roll== a2.roll)
and (a1.class== a2.class);
It seems there are several proprosals here. If it is a query that you'll use in your code, beware of the cost of the queries. Try an 'explain' with your database.