I have problem with this SQL query:
(SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage) ORDER BY tb1.id DESC
for some reason I'm getting:
Table 'tb1' from one of the SELECTs cannot be used in global ORDER clause
any advice?
Thanks
The reason it doesn't work is the outer ORDER BY can't "see" tb1 - it sees the results of the inner subquery. So in a syntactically correct version of your query, you would simply ORDER BY id :
(SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage) ORDER BY id DESC
But, as others are pointing out, this can more simply written as a single query ordered by id
If you put parentheses around your select then the inner table will not be visible outside
SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage, tb1.id DESC
And you can specify multiple columns in one order by clause
When you close your parentheses after select statement, your second order by clause becomes invalid. Instead try merging your order by columns in a single order by statement like the following:
SELECT tb1.id,tb1.bdate,tb1.jumpCard,tb1.publicImage,tb1.lastlogin
FROM users AS tb1, online AS tb2
WHERE tb1.valid='1' AND tb1.sex='female' AND tb1.looking_for='male' AND tb1.id = tb2.member_id
ORDER BY tb1.publicImage, tb1.id DESC
Related
I used the following query
select a.*,b.* from firsttable a left join secondtable b on a.id=b.item_id ORDER BY a.id DESC LIMIT 0,10
To display items from two tables, where the id of the first table is the item_id of the second. My question is , when I try to display this in php , if I want to display a.id i can try with:
while($row=$go->fetch_assoc()){
echo $row['id'];
}
or
while($row=$go->fetch_assoc()){
echo $row['a.id'];
}
since both tables have id,on the first example displays only if there are matching rows from first and second table and displays the id of second table, I want the id of first
and on the second it says undefined index.
Can you explain why is this please?
Edit:
Adding tables for example
id
info
username
id
item.id
username
Both tables have a column that has the same name, so, when using select *, it is ambiguous to which column id relates to.
The only way to remove the ambiguity is to explicitly list all the columns you want to select, using aliases for homonyms:
select
a.id,
b.id b_id, -- alias for b.id
b.item_id
-- more columns here as needed
from firsttable a
left join secondtable b on a.id=b.item_id
order by a.id desc
limit 0,10
This is one of the many reasons why select * is generally considered a bad practice in SQL.
Recommend reading: What is the reason not to use select *?
I have a query given below that returns all the data asked. Then in the next query I need to write I need to restrict the output to where the subquery is greater than 5.
I will show examples but I cannot understand why I cannot do what I am attempting.
Query without restriction
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
order by Times_Checked_Out desc, t1.BOOK_TITLE;
Screenshot of output
Attempt at query with restrictions
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
where Times_Checked_Out > 5
order by Times_Checked_Out desc, t1.BOOK_TITLE;
Error
You can't use a derived column in a where clause, need to use HAVING:
select t1.BOOK_NUM, t1.BOOK_TITLE,
(select count(t2.CHECK_OUT_DATE)
from checkout t2
where t2.BOOK_NUM = t1.BOOK_NUM) as Times_Checked_Out
from book t1
HAVING Times_Checked_Out > 5
order by Times_Checked_Out desc, t1.BOOK_TITLE;
I've come across some PHP code which is generating a query like the below (I've ommited the WHERE clause for clarity)
SELECT user.id FROM users
JOIN table2 ON table2.user_id = users.id
GROUP BY users.id, users.id
Now, it appears to work but I'm weary of the duplicates in GROUP BY. I'm aware that GROUP BY users.id, users.id doesn't make sense and that I can use SELECT distinct(user.id) without grouping.
I'm wondering if it's going to cause problems or if it will always just execute as
SELECT user.id FROM users
JOIN table2 ON table2.user_id = users.id
GROUP BY users.id
This is your query (with the initial "S" added):
SELECT user.id
FROM users JOIN
table2
ON table2.user_id = user.id
GROUP BY user.id, user.id;
This query is not syntactically correct. You have a table named users, which is never referenced, and an alias user which is never defined. If this code is being generated, then there is a bigger error than duplicates in the group by clause.
If the tables are set up correctly, then table2.user_id should always be a valid id in the users table. If so, then the following is a much simpler version of the query:
SELECT distinct t.user_id as id
FROM table2 t;
The difference between this and:
SELECT t.user_id as id
FROM table2 t
GROUP BY t.user_id;
is very minor (they should produce the same execution plans). However, because MySQL supports "hidden columns" -- that is, columns in the select clause that are not aggregated and not in the group by clause -- there are some situations where the distinct and group by are not identical. This does not apply to other databases. And, I would consider these situations to be poorly formed SQL, but they do exist. Here is an example:
SELECT distinct t.user_id as id, t.value
FROM table2 t;
Is not necessarily the same as:
SELECT t.user_id as id, t.value
FROM table2 t
GROUP BY t.user_id;
Although both are syntactically correct MySQL statements.
I am trying to make a view of records in t1 where the source id from t1 is not in t2.
Like... "what records are not present in the other table?"
Do I need to include t2 in the FROM clause? Thanks
SELECT t1.fee_source_id, t1.company_name, t1.document
FROM t1
WHERE t1.fee_source_id NOT IN (
SELECT t1.fee_source_id
FROM t1 INNER JOIN t2 ON t1.fee_source_id = t2.fee_source
)
ORDER BY t1.aif_id DESC
You're looking to effect an anti-join, for which there are three possibilities in MySQL:
Using IN:
SELECT fee_source_id, company_name, document
FROM t1
WHERE fee_source_id NOT IN (SELECT fee_source FROM t2)
ORDER BY aif_id DESC
Using EXISTS:
SELECT fee_source_id, company_name, document
FROM t1
WHERE NOT EXISTS (
SELECT * FROM t2 WHERE t2.fee_source = t1.fee_source_id LIMIT 1
)
ORDER BY aif_id DESC
Using JOIN:
SELECT t1.fee_source_id, t1.company_name, t1.document
FROM t1 LEFT JOIN t2 ON t2.fee_source = t1.fee_source_id
WHERE t2.fee_source IS NULL
ORDER BY t1.aif_id DESC
According to #Quassnoi's analysis:
Summary
MySQL can optimize all three methods to do a sort of NESTED LOOPS ANTI JOIN.
It will take each value from t_left and look it up in the index on t_right.value. In case of an index hit or an index miss, the corresponding predicate will immediately return FALSE or TRUE, respectively, and the decision to return the row from t_left or not will be made immediately without examining other rows in t_right.
However, these three methods generate three different plans which are executed by three different pieces of code. The code that executes EXISTS predicate is about 30% less efficient than those that execute index_subquery and LEFT JOIN optimized to use Not exists method.
That’s why the best way to search for missing values in MySQL is using a LEFT JOIN / IS NULL or NOT IN rather than NOT EXISTS.
However, I'm not entirely sure how this analysis reconciles with the MySQL manual section on Optimizing Subqueries with EXISTS Strategy which (to my reading) suggests that the second approach above should be more efficient than the first.
Another option below (similar to anti-join)... Great answer above though. Thanks!
SELECT D1.deptno, D1.dname
FROM dept D1
MINUS
SELECT D2.deptno, D2.dname
FROM dept D2, emp E2
WHERE D2.deptno = E2.deptno
ORDER BY 1;
I seen topics explaining this but in my case it does not work.
I have query
( SELECT * FROM my_table
left join table2 on table2.id = my_table.id
left join table3 on pension.age = my_table.age
WHERE table3.id IS NULL )
UNION
( SELECT * FROM my_table
left join table2 on table2.id = my_table.id
left join table3 on pension.age = my_table.age
WHERE my_table.id FROM 75 to 245 )
ORDER BY my_table.id ASC, table2.wage DESC, table3.compensation DESC
this does not work saying user_table. or table2. or table3. not found
when i remove it its saying
ORDER BY id ASC, wage DESC, compensation DESC
this somewhat works but not desired result. please assist
Is there part of the code missing? I see no reference to table_fired. Also, aren't those curly braces used as part of an outer join in a larger query? That's why I think there's a larger part of the query missing, which might be relevant.
SELECT * FROM my_table
left join table2 on table2.id = my_table.id
left join table3 on pension.age = my_table.age
WHERE my_table.id IS NULL OR my_table.id FROM 75 to 245
ORDER BY my_table.id ASC, table2.wage DESC, table3.compensation DESC
I replaced your "table_fired" with "my_table" and combined the two subselects into one.
The union operation requires that each of your two queries have exactly the same number of columns in their result set. In mysql, UNION will always use the column names from the frist query - so if the second query uses different column names, they will be mapped by order onto the columns that were defined by the first query.
Your ORDER BY will be applied after the UNION has been run, and so it can only refer to columns that are in the result set of the UNION. These columns are not qualified by table identifiers from the constituent queries (that's why removing the table identifiers from your ORDER BY clause gets rid of the explicit errors).
Beyond that, the problem is likely that your component queries produce multiple columns that have the same name, and are distinguishable only by their table identifiers (for example my_table.id and table2.id). When you use ORDER BY id ASC ..., which of those "id" fields will be used?
Solve this problem by replacing the * with an explicit list of the relevant columns for each of the two component queries. Ensure that each column you select is given a unique name. For Example:
SELECT
my_table.id as my_table_id,
table2.id as table2_id,
table2.compensation as compensation,
table3.wage as wage
...
Your union will then pick up distinctly named columns, and your order by clause would need to refer to those instead of the table-qualified columns in the original queries:
ORDER BY my_table_id ASC, wage DESC, compensation DESC