Why do I receive an error at this join tables? - mysql

I wrote this:
SELECT DISTINCT CATEGORY FROM T AS T1
CROSS JOIN (SELECT *
FROM T
WHERE T.CATEGORY = T1.CATEGORY
ORDER BY CATEGORY DESC
LIMIT 10)
and I receive this
"Unknown column 'T1.CATEGORY' in 'where clause'".
Why?
Update:
My purpose of this is to get 10 posts of any category.

Because T1 is not visible from within the subquery.
Your JOIN also serves no purpose and/or you probably forgot the JOIN condition.

In JOIN condition should use ON keyword
SELECT DISTINCT CATEGORY FROM T AS T1
CROSS JOIN SELECT * FROM T ON T.CATEGORY = T1.CATEGORY
ORDER BY CATEGORY DESC LIMIT 10;

If you need to get 10 posts of each category you can use a query like this:
SELECT CATEGORY, Post
FROM (
SELECT a.CATEGORY, a.Post, count(*) as rn
FROM #T a
JOIN #T b ON a.CATEGORY = b.CATEGORY AND a.Post >= b.Post
GROUP BY a.CATEGORY, a.Post) dt
WHERE rn < 11;

Related

how to use 'inner join' and 'order by' in sql

I want to use inner join and order in my query in php page.
My query :
select
*
from
table1
inner join
table1category
on table1.table1category_id = table1category.id
order by updateDate desc;
'updateDate' is for table1 => error : Column 'updateDate' in order clause is ambiguous
Column 'updateDate' in order clause is ambiguous
Means that updateDate exists in both tables you are trying to use.
If you want to order using this field, you have to specify from which table you want it to be ordered by.
For example:
SELECT
*
FROM table1
INNER JOIN table1category
ON table1.table1category_id = table1category.id
ORDER BY table1.updateDate DESC;
Also, consider that using * on a SELECT with JOINS will get all the columns from all the included tables.
when there is same column in two table then you've to specify the table name with that columns
SELECT
*
FROM table1
INNER JOIN table1category
ON table1.table1category_id = table1category.id
ORDER BY table1.updateDate DESC;
Its because updateDate exists in both tables- table1 and table1category
SELECT
*
FROM table1 t
INNER JOIN table1category tc
ON t.table1category_id = tc.id
ORDER BY t.updateDate DESC;
You have to say which table to use for this field (presents in both tables):
select *
from table1
inner join table1category on table1.table1category_id = table1category.id
order by XXX.updateDate desc;
Replace XXX by table1 or table1category.
You can set aliases on tables too, like:
select *
from table1 as myalias1
inner join table1category as myalias2 on table1.table1category_id = table1category.id
order by XXX.updateDate desc;
Then replace XXX by myalias1 or 2.
You can do the same for selecting datas (for example):
SELECT table1.id AS id, table2.id AS categoryId
Column updateDate in order clause is ambiguous
Try This
SELECT
*
FROM table1 t1
INNER JOIN table1category t2
ON t1.table1category_id = t2.id
ORDER BY t1.updateDate DESC;
I find that using aliases often makes joins easier
SELECT
*
FROM table1 AS alias1
INNER JOIN table1category AS alias2
ON alias1.table1category_id = alias2.id
ORDER BY alias1.updateDate DESC;
You are missing table name
SELECT
*
FROM table1
INNER JOIN table1category
ON table1.table1category_id = table1category.id
ORDER BY table1.updateDate DESC;
SELECT *, table1.updateDate as "Table1 Update Date"
FROM table1
INNER JOIN table1category ON table1.table1category_id = table1category.id
ORDER BY table1.updateDate DESC;
or you can keep alias in ORDER BY clause
SELECT *, table1.updateDate as "Table1 Update Date"
FROM table1
INNER JOIN table1category ON table1.table1category_id = table1category.id
ORDER BY "Table1 Update Date" DESC;
Note
Use keywords always in UPPER case
Better to use alias in SELECT CLAUSE for better understanding, otherwise it will add 1 to updateDate i.e. updateDate1.
Always use alias for same column names
Don't use all columns i.e. * , fetch only required columns
select
*
from
table1 T
inner join
table1category C
on T.table1category_id = C.id
order by T.updateDate desc;

MySQL Subquery SUM Limit

I'm trying to do an subquery with SUM() and LIMIT. This works fine with the following code:
SELECT id,
(
SELECT SUM(number)
FROM (
SELECT number
FROM t2
WHERE u_id = '1'
ORDER BY time ASC
LIMIT 30
) AS temp
) AS test
FROM t1
But I want to do it of course dynamically and with the current row ID.
I changed the Query to the following:
SELECT id,
(
SELECT SUM(number)
FROM (
SELECT number
FROM t2
WHERE u_id = p.id
ORDER BY time ASC
LIMIT 30
) AS temp
) AS test
FROM t1 p
This will give the following error:
Unknown column 'p.id' in 'where clause'
Any ideas how to make it working?
Unfortunately, MySQL limits the scope of table aliases. Oracle is another database that does this.
You can phrase your query as a complicated join:
select t1.id, sum(t2.number)
from t1 p join
t2
on p.id = t2.u_id
where 30 >= (select count(*)
from t2 t22
where t22.u_id = t2.u_id and
t22.time <= t2.time
)
group by t1.id;
Or you can do this with variables:
select p.id, sum(number)
from t1 p join
(select t2.*,
#rn := if(#u = t2.u_id, #rn + 1, if((#u := t2.u_id) is not null, 1, 0)) as rn
from t2
(select #u := 0, #rn := 0) vars
order by t2.u_d, time
) t2
on p.id = t2.u_id
where rn <= 30
group by p.id;
why not just change p.id to t1.id? I'm pretty sure it's because you are aliasing t1 in the first select, and it isn't defined in the subquery. Try an inner join instead.
SELECT id,
(
SELECT SUM(number)
FROM (
SELECT number
FROM t2
INNER JOIN t1 p
on u_id = p.id
ORDER BY time ASC
LIMIT 30
) AS temp
) AS test
FROM t1 p
Try this:
SELECT id, temp2.sum_number as test
FROM t1 p
INNER JOIN
(
SELECT SUM(number) as sum_number, temp.u_id
FROM (
SELECT number, u_id
FROM t2
WHERE u_id = p.id
ORDER BY time ASC
LIMIT 30
) AS temp
) AS temp2 ON temp2.u_id = p.id
I moved subqueries in the join part, so i can access to p.id in the subquery.

MySQL reference outer table alias in subquery error

select c.*
from posts p
join comments c on (p.id=c.post_id)
and c.status = 'A'
and c.id >= (select MIN(id) from (select id from comments where post_id=p.id order by id DESC LIMIT 7) as c2)
where p.comments_count > 0 AND p.id IN (247,245,244,243,242,241)
In the above sql query I get this mysql error Unknown column 'p.id' in 'where clause' it seems like in the subquery p.id isn't able to get referenced. Is there anyway that I can get the posts table id referenced in this subquery?
I think you are trying to fetch latest 7 comments for each post. Could you try this? you can test here http://www.sqlfiddle.com/#!2/a222e/3/0
The First Attempt
I tried below SQL.
SELECT *
FROM comments t1
WHERE post_id IN (247,254,244,243,242,241)
AND id IN (
SELECT id
FROM comments
WHERE t1.id = id
LIMIT 7
);
But I got an error "This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery"
Another Approach
So, I tried self join on comments to generate sequence number.
SELECT id
FROM (
SELECT t1.id, COUNT(*) AS cnt
FROM comments t1 INNER JOIN comments t2
ON t1.post_id = t2.post_id
WHERE t1.id <= t2.id
AND t1.post_id IN (247,254,244,243,242,241)
AND t2.post_id IN (247,254,244,243,242,241)
GROUP BY t1.id
) x
WHERE cnt <= 7;
inner sub-query uses self join and produces cnt column which has sequential value for each comment id of post.
But preceding query only fetches id of comment
Finally to get all columns of comment table, following query should be executed.
SELECT *
FROM comments c INNER JOIN (
SELECT id
FROM (
SELECT t1.id, COUNT(*) AS cnt
FROM comments t1 INNER JOIN comments t2
ON t1.post_id = t2.post_id
WHERE t1.id <= t2.id
AND t1.post_id IN (247,254,244,243,242,241)
AND t2.post_id IN (247,254,244,243,242,241)
GROUP BY t1.id
) x
WHERE cnt <= 7
) t USING (id);
Using User Variables
Actually you have another chance using MySQL user variable. I didn't mention this interesting MySQL feature because I was not sure I understood your question correctly.
SELECT *
FROM (
SELECT post_id, id,
IF (#pid = post_id, #cnt := #cnt + 1, #cnt := 1) AS cnt,
#pid := post_id
FROM comments, (SELECT #pid := 0, #cnt := 0) tmp
WHERE post_id IN (247,254,244,243,242,241)
ORDER BY post_id, id DESC
) x
WHERE cnt <= 7;
Preceding SQL looks like simpler (means good performance) than older join version. but not tested on large data set.
You can only access the outer query 1 level deep. So try doing you where filter on the middle query:
SELECT MIN(id)
FROM (
SELECT id, post_id
FROM comments
ORDER BY id DESC
LIMIT 7
)
WHERE post_id = p.id

Unique result set with inner join query

SELECT
*
FROM `catalog_webdesign_products` t
INNER JOIN tbl_member_registration t1 ont.userid=t1.fld_loginid
WHERE 1
AND t1.fld_member_category_level<9
AND t.product_img IS NOT NULL
ORDER BY RAND() LIMIT 5
In this query , I need rows with unique userid. I had tried 'group by userid' also but then product_img with null value is coming in result set.
yes you can use GROUP BY userid. but your query looks wrong here
INNER JOIN tbl_member_registration t1 on t.userid=t1.fld_loginid
^------------------------space here
try this
SELECT
*
FROM `catalog_webdesign_products` t
INNER JOIN tbl_member_registration t1 on t.userid=t1.fld_loginid
WHERE t1.fld_member_category_level<9
AND t.product_img IS NOT NULL
group by userid
ORDER BY RAND() LIMIT 5
edit:
SELECT
*
FROM (select * from `catalog_webdesign_products` where product_img IS NOT NULL) t
INNER JOIN tbl_member_registration t1 on t.userid=t1.fld_loginid
WHERE t1.fld_member_category_level<9
group by t.userid
ORDER BY RAND() LIMIT 5
For better performance you should move the condition for t1 into join statement. You problem could be the wrong JOIN condition. Try LEFT JOIN instead of INNER JOIN.
More about joins: http://www.w3schools.com/sql/sql_join.asp
SELECT *
FROM `catalog_webdesign_products` t
LEFT JOIN tbl_member_registration t1
ON (t.userid = t1.fld_loginid AND t1.fld_member_category_level < 9)
WHERE t.product_img IS NOT NULL
GROUP BY t.userid
ORDER BY RAND() LIMIT 5

SQL select the last 3 dates from a table

I have a table with lots of fields in mysql
I need a query to return (in the same raw!) the top last 3 dates (dates can have large gaps between them)
ie:
2012/01/20
2012/01/18
2012/01/12
2012/01/10
2012/01/04
etc...
Any help will be appreciated
I must get them in the same row!
This is the query I am trying to use with no success:
SELECT a.id, a.thedate, b.id AS id1, b.thedate AS thedate1, c.id AS id2, c.thedate as thedate2
FROM mytable AS a INNER JOIN mytable AS b ON a.id = b.id INNER JOIN mytable AS c ON b.id=c.id
WHERE c.thedate = SELECT MAX(thedate)
EDIT :
SELECT group_concat(date) FROM (SELECT date FROM my_table ORDER BY date DESC LIMIT 3) AS temp
Corrected-
SELECT group_concat(date) FROM ( select date from table_name order by date desc limit 3) as a
SELECT GROUP_CONCAT(a.date )
FROM (
SELECT date
FROM my_table
ORDER BY date DESC
LIMIT 3
) AS a