Select row if multiple present values are present in another table - mysql

I'm doing a search function on a movie database, I want to give the option to search a film with two genres (ie: crime id:6 and adventure id:7)
I basically want to get a row from title if it has genre_id 6 AND 7 present in the title_genre value. Obviously, this query below isn't working (I understand why it's not but I don't know how to fix it).
Any help please?
SELECT * FROM (`title`, `title_genre`)
WHERE `title`.`active` = 1
AND `title`.`media_id` = title_genre.media_id
AND title_genre.genre_id = 6 AND title_genre.genre_id = 7

You can use the exists to check the existence of other genre_id = 7 in title_genre and also using explicit join makes it much better as
select
t.*,
tg.*
from title t
join title_genre tg on tg.media_id = t.media_id
where
tg.genre_id = 6
and exists(
select 1 from title_genre tg1
where tg1.media_id = t.media_id
and tg1.genre_id = 7
)

Related

Getting max revision number from a view is not working as I thought?

Using MySQL 5.6. I have a view that grabs from one main table called listquotes, and a few other items from other tables. The import columns in the table that are also in the view are Quote # and Revision. We might have 5 different revisions of the same quote number, so our table would look like
id .... Quote# Revision
================================
1 1234 1
2 1234 2
3 1234 3
4 1234 4
5 1234 5
Now on my application GUI we have a dropdown that should allow you to only see the most recent revisions of every quote. Here's how I try to do that
SELECT
...columns...
FROM view_allQuoteInfo
LEFT JOIN listcustomers c ON c.id = view_allQuoteInfo.customerId
WHERE 1=1 AND view_allquoteinfo.customerId = 2453 AND view_allquoteinfo.quoteStatusId = 2 AND view_allquoteinfo.Revision = (SELECT max(t.Revision) FROM view_allquoteinfo t WHERE view_allquoteinfo.`Quote #` = t.`Quote #`)
ORDER BY idx DESC
However, this is not giving me the results I want. Here's an analysis for tihs specific customer I did in excel, some quotes that only have one revision are not showing up like 6668 while others like 4730 which has two revisions is working properly
The where clause for the All table in excel is
1=1
AND view_allquoteinfo.customerId = 2453
AND view_allquoteinfo.quoteStatusId = 2
and the clause for the Latest Table is
1=1
AND view_allquoteinfo.customerId = 2453
AND view_allquoteinfo.quoteStatusId = 2
AND view_allquoteinfo.Revision =
(SELECT max(t.Revision)
FROM view_allquoteinfo t
WHERE view_allquoteinfo.`Quote #` = t.`Quote #`)
the only difference being me trying to get the mlatest revision. The logic looks right to me but obviously MySQL is not interpreting it the way I thought it would.
Any clue as to why it's not working or how I would fix it?
I would expect to see quote 6668 revision one and quote 5963 revision 4 in my "Latest" table, while quote 5963 revision 1,2,3 would not be there.
the condition WHERE view_allquoteinfo.Quote # = t.Quote # inside the subqiery is not clear ( t and view_allquoteinfo are the same table)
so try using a join on subquery group by quote
SELECT
...columns...
FROM view_allQuoteInfo
INNER JOIN (
SELECT v.`Quote #` my_quote, max(v.Revision) max_rev
FROM view_allquoteinfo v
GRUP BY v.`Quote #`
) t ON t.my_quote = view_allQuoteInfo.`Quote #`
AND t.max_rev = view_allQuoteInfo.Revision
LEFT JOIN listcustomers c ON c.id = view_allQuoteInfo.customerId
WHERE view_allquoteinfo.customerId = 2453
AND view_allquoteinfo.quoteStatusId = 2
ORDER BY idx DESC
I figured out a way that works for me. When the user wants all quotes, I leave it the way it is.
When the user wants only the latest revisions, I modify my select query to say
SELECT ...., MAX(view_allquoteinfo.Revision) as 'Revision',...
and then I add a
GROUP BY view_allquoteinfo.'Quote #'.

SQL unwanted results in NOT query

This looks like it should be really easy question, but I've been looking for an answer for the past two days and can't find it. Please help!
I have two tables along the lines of
texts.text_id, texts.other_stuff...
pairs.pair_id, pairs.textA, pairs.textB
The second table defines pairs of entries from the first table.
What I need is the reverse of an ordinary LEFT JOIN query like:
SELECT texts.text_id
FROM texts
LEFT JOIN text_pairs
ON texts.text_id = text_pairs.textA
WHERE text_pairs.textB = 123
ORDER BY texts.text_id
How do I get exclusively the texts that are not paired with A given textB? I've tried
WHERE text_pairs.textB != 123 OR WHERE text_pairs.textB IS NULL
However, this returns all the pairs where textB is not 123. So, in a situation like
textA TextB
1 3
1 4
2 4
if I ask for textB != 3, the query returns 1 and 2. I need something that will just give me 1.
The comparison on the second table goes in the ON clause. Then you add a condition to see if there is no match:
SELECT t.text_id
FROM texts t LEFT JOIN
text_pairs tp
ON t.text_id = tp.textA AND tp.textB = 123
WHERE tp.textB IS NULL
ORDER BY t.text_id ;
This logic is often expressed using NOT EXISTS or NOT IN:
select t.*
from texts t
where not exists (select 1
from text_pairs tp
where t.text_id = tp.textA AND tp.textB = 123
);

Append string to a record's specified column after SELECT command

I have an sql command that returns me a list of duplicated items (in my MySQL database), only two columns, one for the duplicated value and one for the count of duplicated records.
SELECT title, COUNT(*) c FROM posts GROUP BY title HAVING c > 1
title c
---------------
title_1 2
title_a 2
title_b 2
I assume one result looks like this:(and it's an array of arrays)
objId title
------------
1 title_1
2 title_1
So my goal is to append a string to the second item of a result in the array of the duplicated record's like this:
objId title
------------
1 title_1
2 title_1_2
I've found a solution to update the record, but I don't have an idea how could I loop through the results that I get after the first sql command so I can't utilize it in practice.
UPDATE posts SET title = CONCAT(IFNULL(title,''), ' 2');
In pseudo code I would do something like this to create the new string for the title:
result[1].title = (oldTitleString," 2");
save result[1];
I'm new in sql and don't really know about the possibilities, maybe there would be an easier way to do it, so I would really appreciate if somebody could show me how can I get the second record from the duplicated item and extend it with another string.
My solution:
SELECT `objId`,`title`,
(SELECT CONCAT(`title`, '_', `po`.`objId`)
FROM `posts` `p`
WHERE `title` = `po`.`title` && `p`.`objId` < `po`.`objId` LIMIT 1) AS `title_custom`
FROM `posts` `po`
Here is sample fiddle:
http://sqlfiddle.com/#!9/a4164/8
Query looks like this:
select id, title,
concat(title,'_',
(select count(*) from posts p2 where p2.title = p1.title and p2.id <= p1.id)),
title,
count(*) c
from posts p1
group by title
having c > 1

MySQL take duplicate data and combine unique data

With my MySQL database, I want to take data from my temporary table and insert it into my main table, while removing any duplicate data but also taking into consideration the data I already have. This seems to require an update and/or an insert depending on what exists in "data_table" so I really have no idea how to write it or if it is even possible. If this isn't possible, I'd like to know how to accomplish this while not considering what is already in "data_table" which I would think is possible. Thank you for your help!
Existing data_table before running query:
data_table
+-----id-----+-----age-----+-----gender-----+-----color-----+
=============+==============+=================+================+
1 5 m pink,red,purple
data_table_temp
+-----id-----+-----age-----+-----gender-----+-----color-----+
=============+==============+=================+================+
1 5 m red
2 5 m blue
3 5 m red
4 5 m orange
5 6 m red
6 6 m green
7 6 m blue
After query:
data_table
+-----id-----+-----age-----+-----gender-----+-----color-----+
=============+==============+=================+================+
1 5 m pink,red,purple,blue,orange
2 6 m red,green,blue
Here is an approach to this problem which turned out to be harder than I expected.
The idea is to concat the colors that don't match and put them together. There is a bit of a problem assigning ids. Getting the "2" for the second row is a problem, so this just assigned the id sequentially:
select #id := #id + 1 as id,
coalesce(dt.age, dtt.age) as age,
coalesce(dt.gender, dtt.gender) as age,
concat_ws(dt.color,
group_concat(case when find_in_set(dtt.color, dt.color) > 0
then dtt.color
end)
)
from data_table_temp dtt left outer join
data_table dt join
on dt.age = dtt.age and
dt.gender = dtt.gender cross join
(select #id := 0) var
group by coalesce(dt.age, dtt.age), coalesce(dt.gender, dtt.gender);
MySQL doesn't have any string functions to (easily) split a delimited string (like data_table.color).
However, if you have all of the data in data_table_temp's format (one color per row), you can generate the desired results like this:
SELECT DISTINCT age, GROUP_CONCAT(DISTINCT color)
FROM table WHERE [condition]
GROUP BY age;
Optionally adding in gender, as necessary.
Apologies for the half-answer

MySQL Table UNION ISSUE

I'm trying to unite two tables in MySQL, the query I'm using is:
SELECT qa_invoicesitems.item_code, qa_invoicesitems.item_unitprice, qa_invoicesitems.item_subtotal, qa_invoicesitems.item_discount,
qa_invoicesitems.item_total
FROM qa_invoicesitems
RIGHT JOIN qa_invoicesitems_returnlog USING (item_code)
WHERE invoice_code = 17
UNION
SELECT qa_invoicesitems_returnlog.item_code, qa_invoicesitems_returnlog.item_unitprice, qa_invoicesitems_returnlog.item_subtotal,
qa_invoicesitems_returnlog.item_discount, qa_invoicesitems_returnlog.item_total
FROM qa_invoicesitems_returnlog
LEFT JOIN qa_invoicesitems USING (item_code)
WHERE returnlog_code = 9
But I can not behold the desired result.
A graphical example ..
Anyone have any idea how I can get this result?
NOTE: qa_invoicesitems_returnlog Replaces the data.
The codes: 1234, 1585, 23 are taken from (qa_invoicesitems_returnlog), because they exist in both tables, the rest are simply displayed.
Based upon your comments & your image, I'm going to say you want:
all the rows in table 2 where qa_invoicesitems_returnlog = 9
all the rows in table 1 where invoice_code = 17, except for those rows w/ item_id's that are already present in the output from table 2.
So, writing that out as a union, give you:
SELECT qa_invoicesitems_returnlog.item_code as item_code,
qa_invoicesitems_returnlog.item_unitprice as item_unitprice,
qa_invoicesitems_returnlog.item_subtotal as item_subtotal,
qa_invoicesitems_returnlog.item_discount as item_discount,
qa_invoicesitems_returnlog.item_total as item_total
FROM qa_invoicesitems_returnlog
WHERE qa_invoicesitems_returnlog.returnlog_code = 9
UNION
SELECT qa_invoicesitems.item_code as item_code,
qa_invoicesitems.item_unitprice as item_unitprice,
qa_invoicesitems.item_subtotal as item_subtotal,
qa_invoicesitems.item_discount as item_discount,
qa_invoicesitems.item_total as item_total
FROM qa_invoicesitems
WHERE qa_invoicesitems.invoice_code = 17
AND NOT EXISTS (SELECT * FROM qa_invoicesitems_returnlog qir2
WHERE qir2.returnlog_code = 9
and qir2.item_code = qa_invoicesitems.item_code)
The key is the NOT EXISTS clause that excludes from the results from table 1 (qa_invoiceitems) that are already present in the output from table 2 and have a matching item_code.
Why are you using a UNION? I think the following is equivalent to your query:
SELECT qa_invoicesitems.item_code, qa_invoicesitems.item_unitprice,
qa_invoicesitems.item_subtotal, qa_invoicesitems.item_discount,
qa_invoicesitems.item_total
FROM qa_invoicesitems RIGHT JOIN
qa_invoicesitems_returnlog
USING (item_code)
WHERE invoice_code = 15 or returnlogcode = 8
The LEFT and RIGHT joins are doing the same thing because the tables are reversed.