I have 2 tables data and page, in data table I have some records, and some data records id will be store in page table.
Now I want select id and title form data table which is not on page table.
So I wrote this query :
SELECT d.id,d.title
FROM data AS d, page AS p
WHERE d.id NOT IN (p.data_id)
ORDER BY d.title ASC
this query will work, but when page table is empty this query cannot restore records !
use LEFT JOIN
SELECT a.*
FROM data a
LEFT JOIN page b
ON a.ID = b.data_id
WHERE b.data_id IS NULL
ORDER BY a.title ASC
SQLFiddle Demo
SQLFiddle Demo (empty page table)
Here is it with subquery, but without join:
SELECT id, title
FROM data
WHERE id NOT IN (SELECT data_id FROM page)
ORDER BY title ASC
The NOT IN will give you what you want but depending on your database system (and the type of indexes) this will not be the best (fastest) solution. More often then not EXISTS will be faster. But your mileage may vary.
Give it a try:
SELECT id, title FROM data
WHERE NOT EXISTS (SELECT * FROM page WHERE page.data_id = data.id)
ORDER BY title ASC
I think you are trying to determine what data does not have a page:
SELECT d.id, d.title
FROM data d
WHERE d.id NOT IN (
SELECT data_id FROM page
)
ORDER BY d.title ASC;
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 would like to delete my MySQL selection.
Here is my MySQL selection request:
SELECT *
FROM Items
WHERE id_user=1
ORDER
BY id_user
LIMIT 2,1
With this working request, I select the third item on my table which has as id_user: 1.
Now, I would like to delete the item that has been selected by my request.
I am looking for a same meaning request which would look like this :
DELETE FROM Items (
SELECT * FROM Items WHERE id_user=1 ORDER BY id_user LIMIT 2,1
)
The first thing to note is that there is an issue with your query. You are filtering on a unique value of id_user and sorting on the same column. As all records in the resultset will have the same id_user, the actual order of the resultset is undefined, and we cannot reliably tell which record comes third.
Assuming that you have another column to disanbiguate the resultset (ie some value that is unique amongst each group of records having the same id_user), say id, here is a solution to your question, that uses a self-join with ROW_NUMBER() to locate the third record in each group.
DELETE i
FROM items i
INNER JOIN (
SELECT
id,
id_user,
ROW_NUMBER() OVER(PARTITION BY id_user ORDER BY id) rn
FROM items
) c ON c.id = i.id AND c.id_user = i.id_user AND c.rn = 3
WHERE i.id_user=1 ;
Demo on DB Fiddle
You didn't provide the definition of your table. I guess it has a primary key column called id.
In that case you can use this
CREATE TEMPORARY TABLE doomed_ids
SELECT id FROM Items WHERE id_user = 1 ORDER BY id_user LIMIT 2,1;
DELETE FROM Items
WHERE id IN ( SELECT id FROM doomed_ids);
DROP TABLE doomed_ids;
It's a pain in the neck, but it works around the limitation of MySQL and MariaDB disallowing LIMITs in ... IN (SELECT ...) clauses.
You can use the select query to create a derived table and join it back to your main table to determine which record(s) to delete. Derived tables can use the limit clause.
Assuming that the PK is called id, the query would look as follows:
delete i from items i
inner join (SELECT id FROM Items
WHERE id_user=1
ORDER BY id_user LIMIT 2,1) i2 on i.id=i2.id
You need to substitute your PK in place of id. If you have a multi-column PK, then you need to select all the PK fields in the derived table and join on all of them.
I have a simple table USERS:
id | name
----+------
Can you help me with the query that would fetch all rows from the table and:
a) Place 10 rows with highest PK values on top, in id DESC order;
b) Place all remaining rows ordered by name ASC order.
Thank you!
This is a bit of a tricky question. The approach I would take is a join approach. Identify the primary keys for the first group using a join (this is happily fast because you are working with primary keys). Then use the match to that table for the order by:
select t.*
from table t left outer join
(select id
from table t
order by id desc
limit 10
) t10
on t.id = t10.id
order by t10.id desc,
t.name asc;
First question would be: do you really need this in one single query? I'm really not seeing the use case for such a query to be honest.
It'd be easier to just fetch the 10 biggest ids (storing somewhere the 10th biggest), and then fetch the rest in ascending name order (with a restriction on ids being smaller than the 10th biggest).
Otherwise in a single query, something like this would work, but it doesn't seem very efficient to me (maybe someone will have a better idea).
(
SELECT
id, name
from
USERS
ORDER BY id DESC LIMIT 0,10
)
UNION
(
SELECT
id, name
from
USERS
WHERE
id NOT IN (
SELECT id, name from USERS ORDER BY id DESC LIMIT 0,10
)
ORDER BY name ASC
)
(or maybe with a NOT EXISTS - the inner query will be different - instead of the NOT IN)
I have the following mysql query:
SELECT id, sum(views) as total_views
FROM table
WHERE id IN (1,2,3)
GROUP BY id
ORDER BY total_views ASC
If only id 1,3 are found in the database, i still want id 2 to appear, with total_views being set to 0.
Is there any way to do that? This cannot use any other table.
This query hard-codes the list of possible IDs using a sub-query consisting of unions... it then left joins this set of ids to the table containing the information to be counted.
This will preserve an ID in your results even if there are no occurrences:
SELECT ids.id, sum(views) as total_views
FROM (
SELECT 1 AS ID
UNION ALL SELECT 2 AS ID
UNION ALL SELECT 3 AS ID
) ids
LEFT JOIN table
ON table.ID = ids.ID
GROUP BY ids.id
ORDER BY total_views ASC
Alternately, if you had a numbers table, you could do the following query:
SELECT numbers.number, sum(views) as total_views
FROM
numbers
LEFT JOIN table
ON table.ID = ids.ID
WHERE numbers.number IN (1, 2, 3)
GROUP BY numbers.number
ORDER BY total_views ASC
Here's an alternative to Micheal's solution (not a bad solution, mind you -- even with "a lot" of ID's), so long as you're not querying against a cluster.
create temporary table __ids (
id int unsigned primary key
) engine=MEMORY;
insert into __ids (id) values
(1),
(2),
(3)
;
SELECT table.id, sum(views) as total_views
FROM __ids left join table using (id)
GROUP BY table.id
ORDER BY total_views ASC
And if your query becomes complex, I could even conceive of it running more efficiently this way. But, if I were you, I'd benchmark this option with Michael's ad-hoc UNION'ed table option using real data.
in #Michael's answer, if you do have a table with the ids you care about, you can use it as "ids" in place of Michael's in-line data.
Check this fiddle... http://www.sqlfiddle.com/#!2/a9392/3
Select B.ID, sum(A.views) sum from tableB B
left outer join tableA A
on B.ID = A.ID
group by A.ID
also check
http://www.sqlfiddle.com/#!2/a1bb7/1
try this
SELECT id
(CASE 1
IF EXISTS THEN views = mytable.views END
IF NOT EXIST THEN views = 0 END
CASE 2
IF EXISTS THEN views = mytable.views END
IF NOT EXIST THEN views = 0 END
CASE 3
IF EXISTS THEN views = mytable.views END
IF NOT EXIST THEN views = 0 END), sum(views) as total_views
FROM mytable
WHERE id IN (1,2,3)
GROUP BY id
ORDER BY total_views ASC
Does it have to be rows or could you pivot the data to give you one row and a column for every id?
SELECT
SUM(IF (id=1, views, 0)) views_1,
SUM(IF (id=2, views, 0)) views_2,
SUM(IF (id=3, views, 0)) views_3
FROM table
I have a few tables that have similar fields but not exactly the same.
The same fields they have are description (text field) and modified (unixtime)
I would like to select the last modified items from these tables based on unixtime. I cant use UNION since the tables aren't the same and the multiple table select times out.
I've been trying to look for this but no luck, either people are using JOINS or SELECT A., B. FROM table A, table B
How different they are?
Maybe you can get the common fields out:
select t1.name1 as name from table1
union
select t2.name2 as name from table2
Try this:
SELECT
IF (A.modified > B.modified, A.modified, B.modified) AS modified,
IF (A.modified > B.modified, A.description, B.description) AS description,
FROM
(SELECT description, modified FROM A ORDER BY modified DESC LIMIT 1) AS A,
(SELECT description, modified FROM B ORDER BY modified DESC LIMIT 1) AS B
LIMIT 1
However, it's pretty much the same as just doing two queries (only more complicated) so I wouldn't recommend it.
Try adding desc index on 'modified' if your select timesou, and use limit on select to return just one (last) row.
Then you can:
SELECT
A,B,C,D, desc, modified
FROM
TABLEA
UNION ALL
SELECT
CAST(E as <A type>), CAST(F AS <B type>) ..., desc, modified
FROM
TABLE B