I have two tables
Table: color_document
+----------+---------------------+
| color_id | document_id |
+----------+---------------------+
| 180907 | 4270851 |
| 180954 | 4270851 |
+----------+---------------------+
Table: color_group
+----------------+-----------+
| color_group_id | color_id |
+----------------+-----------+
| 3 | 180954 |
| 4 | 180907 |
| 11 | 180907 |
| 11 | 180984 |
| 12 | 180907 |
| 12 | 180954 |
+----------------+-----------+
Is it possible for a query to get a result that looks something like this using multiple color id's to join the two tables?
Result
+----------------+--------------+
| color_group_id | document_id |
+----------------+--------------+
| 12 | 4270851 |
+----------------+--------------+
Since Color Group 12 is the only group that has the exact same set of Colors that Document 4270851 has.
I've got some bad data that i'm being forced to work with so I've had to manufacture the color groups by finding each unique set of color_id's associated with document_id's. I'm trying to then create a new relationship directly between my manufactured color groups and documents.
I know I could probably do something with a GROUP_CONCAT to make a pseudo key of concatenated color ids, but I'm trying to find a solution that would also work in, say, Oracle. Am I barking up the completely wrong tree with this logic?
My ultimate goal is to be able to have a single row in a table that would represent any number of Colors that are associated with a Document to be exported to a completely different system than the one I'm working with.
Any thoughts/comments/suggestions are greatly appreciated.
Thank you in advance for looking at my question.
Do a normal join of the two tables, and count the number of rows in each pairing. Then test whether this is the same as the number of times each of the items appears in the original tables. If all are the same, then all color IDs must match.
SELECT a.color_group_id, a.document_id
FROM (
SELECT color_group_id, document_id, COUNT(*) ct
FROM color_document d
JOIN color_group g ON d.color_id = g.color_id
GROUP BY color_group_id, document_id) a
JOIN (
SELECT color_group_id, COUNT(*) ct
FROM color_group
GROUP BY color_group_id) b
ON a.color_group_id = b.color_group_id and a.ct = b.ct
JOIN (
SELECT document_id, COUNT(*) ct
FROM color_document
GROUP BY document_id) c
ON a.document_id = c.document_id and a.ct = c.ct
SQLFIDDLE
If i understand your question correct you just have to join the two tables and then group the results by color_group_id an document_id.
SQL Fiddle
select color_group_id, document_id
from
color_document cd join
color_group cg
on cd.color_id = cg.color_id
group by color_group_id, document_id
That query will give you this result set:
COLOR_GROUP_ID DOCUMENT_ID
3 4270851
4 4270851
11 4270851
12 4270851
Is that what you want?
Related
I'm trying to join two tables but the problem is that in the second table the value that is the same as in table one has a prefix to it(this tables are generated after opencart instalation - demo data):
Table 1: category
-----------------------------
| category_id | category_name |
|-----------------------------|
| 1 | Components |
| 2 | Laptops |
Table 2: seo_url
------------------------------------------
| seo_url_id | query | keyword |
|------------------------------------------|
| 35 | category_id=1 | components |
| 78 | category_id=2 | laptops |
So the id of a category is in column category_id in Table 1 and it is a number but in Table 2 it is in column query and it has a prefix of category_id= and then the id x(in case of category laptops x being 2).
Can somebody please help me understand how i could join this tables in this situation?
So far i was trying to add category_id= + like this:
SELECT a.id, a.category_name, b.query
FROM category AS a
INNER JOIN seo_url AS b
ON a.category_id = 'category_id=' + b.query
P.S I tried ON 'category_id=' + a.category_id
P.S.S There are also product_id so i don't know if i could use LIKE but i was thinking about it, searched for it and couldn't find a way to make it work.
Thank you! D:
In MySQL, use the function CONCAT(...) that can append strings and numbers, and it is compatible with different versions of that database.
Your fixed query would be:
SELECT a.id, a.category_name, b.query
FROM category AS a
INNER JOIN seo_url AS b
ON CONCAT('category_id=', a.category_id) = b.query;
Your table seo_url already has the 'category_id=' in the values of the field query, so you don't need to append it.
Additionally, I'd recommend you to name the table aliases with more representative names, instead of using a and b.
Hope this helps you to solve your problem!
Use nested REVERSE functions with + 0 to autocast "parse" out the integer.
Query
SELECT
REVERSE(REVERSE('category_id=2') + 0)
UNION ALL
SELECT
REVERSE(REVERSE('category_id=21') + 0)
Result
| REVERSE(REVERSE('category_id=2') + 0) |
|---------------------------------------|
| 2 |
| 21 |
see demo http://sqlfiddle.com/#!9/340e01/530
Use it in your query.
Query
SELECT a.category_id, a.category_name, b.query
FROM category AS a
INNER JOIN seo_url AS b
ON a.category_id = REVERSE(REVERSE(b.query) + 0)
Result
| category_id | category_name | query |
|-------------|---------------|---------------|
| 1 | Components | category_id=1 |
| 2 | Laptops | category_id=2 |
see demo http://sqlfiddle.com/#!9/ef5781/1
I have the following (simplified) three tables:
user_reservations:
id | user_id |
1 | 3 |
1 | 3 |
user_kar:
id | user_id | szak_id |
1 | 3 | 1 |
2 | 3 | 2 |
szak:
id | name |
1 | A |
2 | B |
Now I would like to count the reservations of the user by the 'szak' name, but I want to have every user counted only for one szak. In this case, user_id has 2 'szak', and if I write a query something like:
SELECT sz.name, COUNT(*) FROM user_reservations r
LEFT JOIN user_kar k ON k.user_id = r.user_id
LEFT JOIN szak s ON r.szak_id = r.id
It will return two rows:
A | 2 |
B | 2 |
However I want to every reservation counted to only one szak (lets say the highest id only). I tried MAX(k.id) with HAVING, but seems uneffective.
I would like to know if there is a supported method for that in MySQL, or should I first pick all the user ID-s on the backend site first, check their maximum kar.user_id, and then count only with those, removing them from the id list, when the given szak is counted, and then build the data back together on the backend side?
Thanks for the help - I was googling around for like 2 hours, but so far, I found no solution, so maybe you could help me.
Something like this?
SELECT sz.name,
Count(*)
FROM (SELECT r.user_id,
Ifnull(Max(k.szak_id), -1) AS max_szak_id
FROM user_reservations r
LEFT OUTER JOIN user_kar k
ON k.user_id = r.user_id
GROUP BY r.user_id) t
LEFT OUTER JOIN szak sz
ON sz.id = t.max_szak_id
GROUP BY sz.name;
I am trying to write a query that will find all of our sku's that have option that are a mix of drop downs and swatches.
We have a table that stores this info but is set up a little weird. The column that are important to me are.
-------------------------------------------
sku | option_flag | swatch_flag | sequence
-------------------------------------------
There can be multiple duplicate records of sku because the other columns change depending of how the sku is set up.
My expected results would look like this.
-------------------------------------------
sku | option_flag | swatch_flag | sequence
-------------------------------------------
aa001 | YES | NO | 1
-------------------------------------------
aa001 | YES | YES | 2
-------------------------------------------
aa001 | YES | NO | 3
-------------------------------------------
So far I have this and it is grouping by the sku but it is still including no for option_flag. Maybe instead of grouping by sku, is there a way to ask to sort it by the sequence 1 2 3 - 1 2 3 etc.
SELECT a.*
FROM sku_parent_attributes AS a
INNER JOIN
(SELECT sku
FROM sku_parent_attributes
WHERE option_flag = 'yes'
GROUP BY sku
HAVING COUNT(sku) = 3) AS b
ON a.sku = b.sku;
try this:
SELECT a.*,b.sku
FROM sku_parent_attributes AS a
INNER JOIN
sku_parent_attributes as b
ON a.sku = b.sku
GROUP BY b.sku
HAVING COUNT(b.sku) = 3
the where condition inside the full query and not only inside of the subquery.
For this problem, consider the following 3 tables:
Event
id (pk)
title
Event_Category
event_id (pk, fk)
category_id (pk, fk)
Category
id (pk)
description
Pretty trivial I guess... :) Each event can fall into zero or more categories, in total there are 4 categories.
In my application, I want to view and edit the categories for a specific event. Graphically, the event will be shown together with ALL categories and a checkbox indicating whether the event falls into the category. Changing and saving the choice will result in modifocation of the intermediate table Event_Category.
But first: how to select this for a specific event? The query I need will in fact always return 4 rows, the number of categories present.
Following returns only the entries for the categories the event with id=11 falls into. Experimenting with outer joins did not give more rows in the result.
SELECT e.id, c.omschrijving
FROM Event e
INNER JOIN Event_Categorie ec ON e.id = ec.event_id
INNER JOIN Categorie c ON c.id = ec.categorie_id
WHERE e.id = 11
Or should I start with the Category table in the query? Hope for some hints :)
TIA, Klaas
UPDATE:
Yes I did but still have not found the answer. But I have simplified the issue by omitting the Event table from the query because this table is only used to view the Event descriptions.
SELECT * from Categorie c LEFT JOIN Event_Categorie ec ON c.id = ec.categorie_id WHERE ec.event_id = 11;
The simplified 2-table query only uses the lookup table and the link table but still returns only 2 rows instead of the total of 4 rows in the Categorie table.
My guess would be that the WHERE clause is applied after the joining, so the rows not joined to the link table are excluded. In my application I solved the issues by using a subquery but I still would like to know what is the best solution.
What you want is the list of all categories, plus information about whether that category is in the list of categories of your event.
So, you can do:
SELECT
*
FROM
Category
LEFT JOIN Event_Category ON category_id = id
WHERE
event_id = 11
and event_id column will be NULL on the categories that are not part of your event.
You can also create a column (named has_category below) that you will use to see if the event has this category instead of comparing with NULL:
SELECT
*,
event_id IS NOT NULL AS has_category
FROM
Category
LEFT JOIN Event_Category ON category_id = id
WHERE
event_id = 11
EDIT: This seems exactly what you say you are doing on your edit. I tested it and it seems correct. Are you sure you are running this query, and that rows with NULL are not somehow ignored?
The query
SELECT * FROM Categorie;
returns 4 rows:
+----+--------------+-------------------------------------+--------------------------------------+
| id | omschrijving | afbeelding | afbeelding_klein |
+----+--------------+-------------------------------------+--------------------------------------+
| 1 | Creatief | images/categorieen/creatief420k.jpg | images/categorieen/creatief190k.jpg |
| 2 | Sportief | images/categorieen/sportief420k.jpg | images/categorieen/sportief190kr.jpg |
| 4 | Culinair | images/categorieen/culinair420k.jpg | images/categorieen/culinair190k.jpg |
| 5 | Spirit | images/categorieen/spirit420k.jpg | images/categorieen/spirit190k.jpg |
+----+--------------+-------------------------------------+--------------------------------------+
4 rows in set (0.00 sec)
BUT:
The query
SELECT *
FROM Categorie
LEFT JOIN Event_Categorie ON categorie_id = id
WHERE event_id = 11;
returns 2 rows:
+----+--------------+-------------------------------------+-------------------------------------+----------+--------------+
| id | omschrijving | afbeelding | afbeelding_klein | event_id | categorie_id |
+----+--------------+-------------------------------------+-------------------------------------+----------+--------------+
| 1 | Creatief | images/categorieen/creatief420k.jpg | images/categorieen/creatief190k.jpg | 11 | 1 |
| 4 | Culinair | images/categorieen/culinair420k.jpg | images/categorieen/culinair190k.jpg | 11 | 4 |
+----+--------------+-------------------------------------+-------------------------------------+----------+--------------+
2 rows in set (0.00 sec)
So I still need the subquery... and the LEFT JOIN is not effective in showing all rows of the CAtegorie table, regardless whether there is a match with the link table.
This query, however, does what I want it to do:
SELECT *
FROM Categorie c
LEFT JOIN (SELECT * FROM Event_Categorie ec WHERE ec.event_id = 11 ) AS subselect ON subselect.categorie_id = c.id;
Result:
+----+--------------+-------------------------------------+--------------------------------------+----------+--------------+
| id | omschrijving | afbeelding | afbeelding_klein | event_id | categorie_id |
+----+--------------+-------------------------------------+--------------------------------------+----------+--------------+
| 1 | Creatief | images/categorieen/creatief420k.jpg | images/categorieen/creatief190k.jpg | 11 | 1 |
| 2 | Sportief | images/categorieen/sportief420k.jpg | images/categorieen/sportief190kr.jpg | NULL | NULL |
| 4 | Culinair | images/categorieen/culinair420k.jpg | images/categorieen/culinair190k.jpg | 11 | 4 |
| 5 | Spirit | images/categorieen/spirit420k.jpg | images/categorieen/spirit190k.jpg | NULL | NULL |
+----+--------------+-------------------------------------+--------------------------------------+----------+--------------+
4 rows in set (0.00 sec)
The issue is that you have filtered the results by the eventid. As you can see in your results, two of the categories (Sportief and Spirit) do not have events. So the correct SQL statement (using SQL Server syntax; some translation may be required) is:
SELECT *
FROM Categorie
LEFT JOIN Event_Categorie ON categorie_id = id
WHERE (event_id IS NULL) OR (event_id = 11);
Finally I found the right query, no subselect is necessary. But the WHERE clause works after the joining and therefore is no part of the join anymore. THe solution is extending the ON clause with an extra condition. Now all 4 rows are returned with NULL for the non-matching Categories!
SELECT *
FROM Categorie
LEFT JOIN Event_Categorie ON categorie_id = id AND event_id = 11;
So the bottom line is that putting an extra condition in the ON clause has different effect than filtering out rows by the same condition in the WHERE clause!
Alright so I have a table, in this table are two columns with ID's. I want to make one of the columns distinct, and once it is distinct to select all of those from the second column of a certain ID.
Originally I tried:
select distinct inp_kll_id from kb3_inv_plt where inp_plt_id = 581;
However this does the where clause first, and then returns distinct values.
Alternatively:
select * from (select distinct(inp_kll_id) from kb3_inv_plt) as inp_kll_id where inp_plt_id = 581;
However this cannot find the column inp_plt_id because distinct only returns the column, not the whole table.
Any suggestions?
Edit:
Each kll_id may have one or more plt_id. I would like unique kll_id's for a certain kb3_inv_plt id.
| inp_kll_id | inp_plt_id |
| 1941 | 41383 |
| 1942 | 41276 |
| 1942 | 38005 |
| 1942 | 39052 |
| 1942 | 40611 |
| 1943 | 5868 |
| 1943 | 4914 |
| 1943 | 39511 |
| 1944 | 39511 |
| 1944 | 41276 |
| 1944 | 40593 |
| 1944 | 26555 |
If you do mean, by "make distinct", "pick only inp_kll_ids that happen just once" (not the SQL semantics for Distinct), this should work:
select inp_kll_id
from kb3_inv_plt
group by inp_kll_id
having count(*)=1 and inp_plt_id = 581;
Get all the distinct first (alias 'a' in my following example) and then join it back to the table with the specified criteria (alias 'b' in my following example).
SELECT *
FROM (
SELECT
DISTINCT inp_kll_id
FROM kb3_inv_plt
) a
LEFT JOIN kb3_inv_plt b
ON a.inp_kll_id = b.inp_kll_id
WHERE b.inp_plt_id = 581
in this table are two columns with
ID's. I want to make one of the
columns distinct, and once it is
distinct to select all of those from
the second column of a certain ID.
SELECT distinct tableX.ID2
FROM tableX
WHERE tableX.ID1 = 581
I think your understanding of distinct may be different from how it works. This will indeed apply the where clause first, and then get a distinct list of unique entries of tableX.ID2, which is exactly what you ask for in the first part of your question.
By making a row distinct, you're ensuring no other rows are exactly the same. You aren't making a column distinct. Let's say your table has this data:
ID1 ID2
10 4
10 3
10 7
4 6
When you select distinct ID1,ID2 - you get the same as select * because the rows are already distinct.
Can you add information to clear up what you are trying to do?