How to query the look up table for unique values? - mysql

I have a recipe table that is structured like this:
product2recipe
id | productid | recipeid
I want to eliminate insertion of duplicate values. Basically a recipe can contain 1 or more productid. So it looks like this:
1 | 1 | 1
2 | 2 | 1
3 | 1 | 2
4 | 5 | 3
The user can submit a new recipe, if the recipe contains similar value like:
id | 1 | 4
id | 2 | 4
Then it should not submit, because the table already have duplicate values, recipeid 1 contains productid 1 and 2 already. If it is:
id | 1 | 5
id | 3 | 5
Then it should submit since this is a unique combination.
How can I query my table optimally? I'm afraid that it might stall my database server since there's possibly many combinations.

The example you have provided does exactly tells us what you want because those records does not exist on the table.
But anyway, here's a way to enforce a UNIQUE constraint for compound column in your table,
ALTER TABLE product2recipe ADD CONSTRAINT tb_uq UNIQUE(productid, recipeid)
SQLFiddle Demo
uncomment the ALTER TABLE statement in the demontration link above and see what happens

Given a known set of products for a "new" recipe, I would suggest running the following query:
select recipeid
from product2recipe
group by recipeid
having count(distinct productid) =
count(distinct case when productid in (?,?,...) then productid end)
- any recipes returned will have the same set of products as the "new" recipe; your application should then be programmed to reject such "new" recipes.

Related

SQL: delete old record and keep latest record when duplicate

I'm working on a small search engine project and I need some help with a SQL query. My table looks like this (example):
user_id | group_id
---------------------------
1 | 2
2 | 2
2 | 3
3 | 2
i want to delete the old records and leave the newest one when the user_id column is duplicated
How should the select query look like?

MySQL - Is it possible to sort data from one table based on the presence of data in another?

I have a table that I want to be able to sort based on the existence of data in another, related table, but I'm not sure what I want to do is possible in a single query.
For example, say I have a Products table and a Notifications table. Each table has a bunch of columns, but the important ones for this purpose is an Active column, and a foreign key in the Notifications table that references the Products table. Each row in the Products table may be referenced 0 to N times in the Notifications table.
Products Notifications
ProductID | Active NotificationID | ProductID | Active | Type
----------+------- ---------------+-----------+--------+-----
1 | 1 1 | 2 | 1 | 2
2 | 1 2 | 3 | 0 | 1
3 | 1 3 | 3 | 1 | 1
4 | 1 4 | 5 | 1 | 1
5 | 1 5 | 3 | 1 | 1
One use case I'd like to support is to sort the data from the Products table based on whether or not there is an active Notification of a particular Type (Type=1) for the Product. So in the above example, Products 3 and 5 to be collated first or last, but all five products should still be in the result set.
I haven't been able to figure out a way to manage this in a single SELECT statement. I can easily pull just the Products that do or don't have an active Notification of a certain type, but I can't figure out a way to get them all at once and sort them based on that. Is it possible or do I just need to run a couple of separate queries?
What you want is accomplished through a join and aggregation. I would suggest summarizing the notifications table as a subquery to get what you want:
select p.*
from products p left join
(select productId, count(*) as cnt
from notifications n
where active = 1
group by productid
) n
on p.productid = n.productid
order by (n.productid is not null) desc;
This structure gives you the flexibility of using the existence (as shown above), or the count, or including the count in the select list.

How to select multiple entries with the same value in one column in T-SQL

So, I am working in Visual Studio 2013. And I have a table like this:
id | fk | data
----------------------
1 | 1 | something1
2 | 1 | something2
3 | 1 | something3
. | . | ...
. | . | ...
6 | 2 | ...
The fk is a foreign key to another table. I want to select all the rows which have the same fk. There is an undefined number of the same fk entries (there could be 5 rows with value 1 and 3 rows with value 2, etc.) But, I want to be able to switch said fk in my program so that when i put the DB in a Form in Visual Studio, clicking a button next would get me the next value of the fk. For example, I would like the first result to come out like this:
id | fk | data
----------------------
1 | 1 | something1
2 | 1 | something2
3 | 1 | something3
And when I click next to get me to the next entry, the result would be:
id | fk | data
----------------------
6 | 2 | ....
7 | 2 | ....
Is there a way in SQL to combine just the results with the same fk value? All of the solutions I have found so far gave me all of the fk values (all entries). I haven't found a way to get just all the entries with a single, unique value in the fk column.
You're looking for a basic SELECT statement with a WHERE clause:
SELECT
id, fk, data
FROM
your_table_name
WHERE
fk = 1
I can't help you with the VisualStudio stuff though, but you'll just have to repeat the same query incrementing the fk value in the WHERE clause

Querying entries by IDs aggregated by two different tables

I have the following table structure
table object_to_profile
objectID | profileID
1 | 1
2 | 1
3 | 1
2 | 2
table object_to_task
taskID | objectID | profileID
1 | 1 | 1
1 | 4 | 1
1 | 2 | 2
The table object_to_task is built the following way:
I show the user checkboxes, which basically represent the object_to_profile table.
The user can select objects out of the table and save them into the object_to_task table.
The Administrator can later remove the object from the table. But if the user has already selected some of the object from the profiles, it should be still visible to him. So I need a query to select all object that are currently in the profiles plus all objects that were in the table and have been selected by the user.
As you can see, objectID 4 is no longer in the object_to_profile table, but has been selected by the user.
What would be a way to the objectIDs together?
As far as i understand, you just need to union 2 result sets
select ObjectID from object_to_profile
union
select ObjectID from object_to_task where taskID = 1

Trying to find a single record based on a group of records where there is a 100% match in mysql

I've been chasing my tail on this one. I have a single table (keeping it simple for this example).
LogID (Primary Key)
UserID (Foreign Key)
Skipped (Tiny Int, default 0) can be 1 or 0
This is a one to many relation, this table being the 'many' in this join
A user ie: John Smith might have a UserID of 10. Each record can have a skipped = 1 or Skipped = 0 depending on the instance for the particular record.
Here is a simple break down of data
1 | 10 | 1
2 | 10 | 0
3 | 10 | 1
4 | 10 | 0
So this user is in there 4 times. 2 records show skipped (1) and 2 records show not skipped (0).
I need to create a query to find users that are 100% skipped. So a person who looks like this:
1 | 11 | 1
2 | 11 | 1
3 | 11 | 1
4 | 11 | 1
If Skipped is 0 I don't want that user. Users can be mixed (skipped yes and no), so I need to find a user that is 100% skipped only. I will need it GROUPed by UserID or at least DISTINCT handling on it when found, so I get single users (no dups). I've been spinning my head around on GROUP BYs, HAVINGS, COUNTs and SUMs to get this, but I keep getting caught up on the 100% portion of the query.
I'm using MySQL 5.1.56
Any suggestions are greatly appreciated.
Thanks!
hanji
select userid
from table
group by userid
having count(userid) = sum(if(skipped = 1,1,0))
select distinct userid
from table
where userid not in
(select userid from table where skipped = 0)