For simplicity, suppose I have a table transactions with id as the primary key. Currently there are only 10 rows in the table with id from 1 to 10.
I have a list of ids: {9,10,11,12}. This list is not stored in the database.
I want to query the database for the ids not in the transactions table. In the case above I want to get 11, 12.
What's the best way to way to write this query?
Currently I just query SELECT * FROM transactions WHERE id IN (9,10,11,12). And do my intersection in code. I'm wondering is I can do it all in one step in SQL.
You can do this with a subquery containing the ids. Here is one way:
select ids.id
from (select 9 as id union all select 10 union all select 11 union all select 12
) ids
where not exists (select 1 from transactions t where t.id = ids.id);
Returning rows from a table called transactions seems inefficient -- way too much data going back and forth for what you need. (Although you only have 10 rows, so this isn't a big deal with your data size.)
An alternative approach would be to use the EXCEPT clause. For example;
select 9 as id union all select 10 union all select 11 union all select 12
except select id from transactions
Related
Sorry if the title is misleading, I don't really know the terminology for what I want to accomplish. But let's consider this table:
CREATE TABLE entries (
id INT NOT NULL,
number INT NOT NULL
);
Let's say it contains four numbers associated with each id, like this:
id number
1 0
1 9
1 17
1 11
2 5
2 8
2 9
2 0
.
.
.
Is it possible, with a SQL-query only, to count the numbers of matches for any two given numbers (tuples) associated with a id?
Let's say I want to count the number of occurrences of number 0 and 9 that is associated with a unique id. In the sample data above 0 and 9 does occur two times (one time where id=1 and one time where id=2). I can't think of how to write a SQL-query that solves this. Is it possible? Maybe my table structure is wrong, but that's how my data is organized right now.
I have tried sub-queries, unions, joins and everything else, but haven't found a way yet.
You can use GROUP BY and HAVING clauses:
SELECT COUNT(s.id)
FROM(
SELECT t.id
FROM YourTable t
WHERE t.number in(0,9)
GROUP BY t.id
HAVING COUNT(distinct t.number) = 2) s
Or with EXISTS():
SELECT COUNT(distinct t.id)
FROM YourTable t
WHERE EXISTS(SELECT 1 FROM YourTable s
WHERE t.id = s.id and s.id IN(0,9)
HAVING COUNT(distinct s.number) = 2)
The query take more than 6 seconds for 4 million records. Any other procedure can be done to minimize the query time.
SELECT title_id, count(title_id) as count
FROM `title_keywords`
WHERE keyword_id in (1,2,3,4,5,6,7,8,9)
GROUP BY title_id
ORDER BY count desc
Index and unique columns
Added composite index too
Because the COUNT function needs to potentially touch every record in each group, there may not be much which can speed up the aggregation. However, we might be able to take advantage of an index to speed up the WHERE clause:
CREATE INDEX idx ON title_keywords (keyword_id, title_id);
You could also try reversing the order of the index columns, and in either case perhaps check the execution plan using EXPLAIN. The reason this index might work is that it would allow MySQL to quickly access on the matching keyword_id records. The index also covers title_id, so that this value would be available in the leaf nodes of the B-tree.
try avoid IN clause using a INNER JOIN
SELECT title_id, count(title_id) as count
FROM title_keywords
INNER JOIN (
SELECT 1 col1
UNION
SELECT 2
UNION
SELECT 3
UNION
SELECT 4
UNION
SELECT 5
UNION
SELECT 6
UNION
SELECT 7
UNION
SELECT 8
UNION
SELECT 9
) t t.col1 = title_keywords.keyword_id
group by title_id
order by count desc
and be sure you have a proper index on
table title_keywords columns( keyword_id, title_id )
Is it possible using pure SQL to add multiple rows into a table based on a value in a given field?
I have table named products, for simplicity this is an example:
id, views
1, 4
For that row, I want to insert 4 rows into another table. How can I do this?
I've written a PHP script to do this but would prefer a SQL version but I have no idea how to even start.
In order to do this, you need a way to generate values. If you have just a handful, you can do this manually:
insert into table(id)
select p.id, n.n as which
from products p join
(select 1 as n union all select 2 union all select 3 union all select 4 union all select 5
) n
on p.views <= n.n;
If you have a table of numbers you can use that as well.
I'm using the UNION operator to select results from two different tables. I want results from the first table result to come before those from the second table.
For example: I have the tables customer_coupons and segment_coupons. Both tables have a column named coupon_id. When I run a query involving a UNION of these two tables, it returns the correct records, but they are not the order I want: It gives me the coupon_ids of both tables mixed in ascending order, but I want to show ALL coupon_ids of the first table and then ALL coupon_ids of the second table.
Here's the query as it currently exists:
SELECT coupon_id
FROM customer_coupons
UNION
SELECT coupon_id
FROM segment_coupons;
How can I change this so that all results from the first half of the query come before all results of the second half?
Put in a fixed table-identifying field:
(SELECT 1 AS source_table, coupon_id
FROM customer_coupons)
UNION ALL
(SELECT 2 AS sourcE_table, coupon_id
FROM segment_coupons)
ORDER BY source_table, coupon_id
Note the brackets around the individual queries. This forces MySQL to apply the order by to the result of the union, not to the 2 sub-query.
SELECT * FROM (
SELECT coupon_id, 1 as myorder
FROM customer_coupons
UNION
SELECT coupon_id 2 as myorder
FROM segment_coupons)
Order by myorder
I have a table in a MySQL database with an ID column. This is not a key of the table and several rows can have the same ID.
I don't really know SQL but I already figured out how to obtain the number of distinct IDs:
SELECT COUNT(DISTINCT ID) FROM mytable;
Now I want to count only those IDs which appear more than 2 times in the table.
So if the ID column contains the values
3 4 4 5 5 5 6 7 7 7
the query should return 2.
I have no idea how to do this. I hope someone can help me!
Btw, my table contains a huge number of rows. So if there are several possibilities I would also be happy to know which solution is the most efficient.
Try this:
SELECT COUNT(ID) FROM (
SELECT ID FROM mytable
GROUP BY ID
HAVING COUNT(ID) > 2) p
select count(*) from
(select count(id) as cnt,id from mytable group by id) da
where da.cnt>2
The inner query will give you how many elements does each id have. And the outer query will filter this.
SELECT
COUNT(ids)
FROM
(SELECT
COUNT(ID)AS ids
FROM
mytable
GROUP BY
ID
HAVING
ids>2
)AS tbl1
Updated :
SELECT count(ID)
FROM (
SELECT ID FROM mytable
GROUP BY ID
HAVING count(ID) > 2
) p
should do what you need