I got two tables. Table one with 3 category columns. Table 2 with 2 category columns. I try to write a query that compare this category columns and shows me the data wich is in one of the threee columns of table 1, but not in one of the two columns of table 2.
e.g.
table 1
ID product cat1 cat2 cat3
10001 product a A B C
10001 product a D E NULL
10001 product a F G H
10002 product b B C D
... ... ... ... ...
table 2
ID product cat1 cat2
10001 product a D E
10001 product a D F
10001 product a G A
10002 product b A C
... ... ... ... ...
The output of the query should look something like that:
product_id not_in_cat
10001 B
10001 C
10001 H
10002 B
10002 D
But i dont know how i can realize it. I tried to do this with a subquery and the "NOT IN" command. But this way i got many subqueries, for each combination of t1.cat1 - t2.cat1, t1.cat2 - t2.cat2, and so on.
And this way i got only the cats which are not in the same row.
Maybe someone can help me to figure out, which way is the best to achieve the desired result.
The query is performed on a MS SQL Server with a openquery to a MySQL and a oracle db server. But i think its more a logic problem.
I think you should "normalize" the data and do the equivalent of a full outer join using union all and group by. This looks like:
select id, cat
from (select id, cat1 as cat, 1 as which from table1 union all
select id, cat2 as cat, 1 as which from table1 union all
select id, cat3 as cat, 1 as which from table1 union all
select id, cat1 as cat, 2 as which from table2 union all
select id, cat2 as cat, 2 as which from table2
) ic
where cat is not null
group by id, cat
having min(which) = max(which);
This finds the categories that are in only one of the tables. Note: If you know that there are no duplicates in either table, then having count(*) = 1 also works.
And, if you want to know the table where the category is present, then ask another question. That is a bit different from the question that you did ask.
Related
I have tblOuts that tracks Skus out of inventory by Category and date:
OutDate
Category
Sku
20210322
A
111
20210322
B
222
20210323
A
111
20210323
B
222
20210323
B
333
20210324
D
444
I created a crosstab that will show the count of Skus by Category and OutDate:
Category
20210322
20210323
20210324
A
1
1
B
1
2
D
1
How can I modify the crosstab to also show Category C, even though it doesn't have any data in my table yet?
Category
20210322
20210323
20210324
A
1
1
B
1
2
C
D
1
Normally I would create a separate table that listed all Categories and left join it to the crosstab. But I can't think of an ideal way to do so.
SELECT tblCategories.Category, qryCrosstab.*
FROM tblCategories LEFT JOIN qryCrosstab ON tblCategories.Category = qryCrosstab.Category
gives me two Category fields, which I don't want:
tblCategories.Category
qryCrosstab.Category
20210322
20210323
20210324
Alternately, I could do the following, but would need to modify my query every time a new date is added to the table:
SELECT tblCategories.Category, qryCrosstab.20210322, qryCrosstab.20210323, qryCrosstab.20210324
FROM tblCategories LEFT JOIN qryCrosstab ON tblCategories.Category = qryCrosstab.Category
Yes, I see what you mean by "doubled":
SELECT
Category.Category,
qOut.*
FROM
Category
LEFT JOIN
qOut ON Category.Category = qOut.Category;
Can't you just ignore one of those category fields?
I want to join columns from multiple tables to one column, in my case column 'battery_value' and 'technical_value' into column 'value'. I want to fetch data for only given category_ids, but because of UNION, I get data from other tables as well.
I have 4 tables:
Table: car
car_id model_name
1 e6
Table: battery
battery_category_id car_id battery_value
1 1 125 kW
Table: technical_data
technical_category_id car_id technical_value
1 1 5
3 1 2008
Table: categories
category_id category_name category_type
1 engine power battery
1 seats technical
3 release year technical
From searching, people are suggesting that I use union to join these columns. My query now looks like this:
SELECT CARS.car_id
category_id,
CATEGORIES.category_name,
value,
FROM CARS
left join (SELECT BATTERY.battery_category_id AS category_id,
BATTERY.car_id AS car_id,
BATTERY.value AS value
FROM BATTERY
WHERE `BATTERY`.`battery_category_id` IN (1)
UNION
SELECT TECHNICAL_DATA.technical_category_id AS category_id,
TECHNICAL_DATA.car_id AS car_id,
TECHNICAL_DATA.value AS value
FROM TECHNICAL_DATA
WHERE `TECHNICAL_DATA`.`technical_category_id` IN (3))
tt
ON CARS.car_id = tt.car_id
left join CATEGORIES
ON category_id = CATEGORIES.id
So the result I want is this, because I only want to get the data where category_id 1 is in battery table:
car_id category_id category_name technical_value
1 1 engine power 125 kW
1 3 release year 2008
but with the query above I get this, category_id 1 from technical table is included which is not something I want:
car_id category_id category_name value
1 1 engine power 125 kW
1 1 seats 125 kW
1 3 release year 2008
How can get exclude the 'seats' row?
For the results you want, I don't see why the cars table is needed. Then, you seem to need an additional key for the join to categories based on which table it is referring to.
So, I suggest:
SELECT tt.*, c.category_name
FROM ((SELECT b.battery_category_id AS category_id,
b.car_id AS car_id, b.value AS value,
'battery' as which
FROM BATTERY b
WHERE b.battery_category_id IN (1)
) UNION ALL
(SELECT td.technical_category_id AS category_id,
td.car_id AS car_id, td.value AS value,
'technical' as which
FROM TECHNICAL_DATA td
WHERE td.technical_category_id IN (3)
)
) tt LEFT JOIN
CATEGORIES c
ON c.id = tt.category_id AND
c.category_type = tt.which;
That said, you seem to have a problem with your data model, if the join to categories requires "hidden" data such as the type. However, that is outside the scope of the question.
So, I have an intermediate table in MySQL called "Inventory", with two PKs: idMovie and idSubsidiary. That table looks like this:
----------------------------------
idMovie (int) | idSubsidiary (int)
----------------------------------
0 | 0
2 | 0
1 | 1
3 | 2
----------------------------------
I want to select the IDs of the pair of subsidiaries that have exactly the same movies.
For that, I was thinking about something like this:
select distinct inv1.idSubsidiary, inv2.idSubsidiary
from inventory inv1
join inventory inv2
on inv1.idSubsidiary <> inv2.idSubsidiary
where not exists (
SELECT i1.idSubsidiary, i1.idMovie , i2.idSubsidiary, i2.idMovie
FROM inventory i1
INNER JOIN inventory i2 ON i1.idMovie = i2.idMovie
WHERE (i1.idSubsidiary= inv1.idSubsidiary and i2.idSubsidiary= inv2.idSubsidiary
AND i2.idSubsidiary IS NULL
)
The result I'm looking for would be something like this:
idSubsidiary | idSubsidiary
---------------------------
0 | 1
3 | 4
So, subsidiary 0 and 1 have the same identical movies on the inventory, same with 3 and 4.
However, the previously shown query is not working. Basically, the query looks up for couples of SubsidiaryID's on Inventory and then runs a nested query to find if the first Subsidiary have any movie that the second Subsidiary does not have. If they don't, it selects both.
However, the nested query is not working. As I said, I want to do a left join of the same table without the inner part.
Any help is much appreciated :)
The simplest method in MySQL is to do double aggregation:
select movies, group_concat(idSubsidiary) as subsidiaries
from (select i.idSubsidiary, group_concat(idMovie order by idMovie) as movies
from inventory i
group by i.idSubsidiary
) s
group by movies
having count(*) > 1;
Each row in the result set is a set of movies with the set of ids that have exactly those movies. Those are the duplicates.
I rewrite a stackoverflow question:
I have a table and data like this:
ID | Name | Type
1 Apple A
2 Boy A
3 Cat B
4 Dog C
5 Elep C
6 Fish C
What SELECT I must use to obtain this result:
4 Dog C
5 Elep C
6 Fish C
1 Apple A
2 Boy A
3 Cat B
I dont want this one ...:
select ID, Name, Type from TABLE where GROUP BY Type order by count(*) desc;
...whith this result:
4 Dog C
1 Apple A
3 Cat B
Thanks
The issue you've got is the grouping command affects the values you are trying to select. One way around this is to derive the count (typetotal) for each type, in its own table like:
SELECT
Type,
COUNT(*) AS typetotal
FROM
TABLE
GROUP BY
Type
We are now able to link the Type to the typetotal to your new SELECT query using the INNER JOIN command, allowing you to sort the query as shown below:
SELECT
TABLE.ID,
TABLE.Name
TABLE.Type,
FROM
(
SELECT
Type,
COUNT(*) AS typetotal
FROM
TABLE
GROUP BY
Type
)
AS tblTypeCount
INNER JOIN
TABLE
ON
TABLE.Type = tblTypeCount.Type
ORDER BY
tblTypeCount.typetotal DESC
I hope I've explained this in a way that makes sense, if you need any clarification, or have any suggestions let me know.
I have related products table like this:
product_id | related_product_id
1 | 2
1 | 3
1 | 4
2 | 1
3 | 1
4 | 1
But instead I would like to insert new related product ids so they all match. I.E. If product 1 has 2,3,4 I wan't that products 2,3,4 also have the same related ids which are missing.
Not sure how it's called but is this possible? Many thanks.
You can use a SELECT query as the source of data in an INSERT
INSERT INTO related_products (product_id, related_product_id)
SELECT r1.product_id, r2.related_product_id
FROM related_products AS r1
CROSS JOIN related_products AS r2
WHERE r1.product_id != 1
AND r2.product_id = 1
This join will get all of product 1's related products and combine them with all the other product IDs.
You can give this query a try (untested, make a backup first!):
insert into related_products (product_id,related_product_id) (select related_product_id, product_id from related products);
I would suggest to user bidirectional condition to get the inter related products. For example if you apply condition on single column product_id, you will not get visa-versa result. But, if you check that condition on both column, you will get the result.
For example:
select related_product_id, product_id from products where related_product_id=1 OR product_id=1
This will give your related product id in either related_product_id or product_id.
Same you can get it for product 2 i.e.
select related_product_id, product_id from products where related_product_id=2 OR product_id=2
This will give all your related product id in either related_product_id or product_id.