I have a list of items in MySQL table each one has a group number & unique item number.
I'm Trying to select records that mach 2 criterias.
First I need to select record that satisfies group & item numbers. If none found i want records selected that just belongs to a group.
Only one record has to be selected either way.
SELECT *
FROM YourTable
WHERE GroupID = :group
ORDER BY ItemID = :item DESC
LIMIT 1
LIMIT 1 makes it return just one record. The ORDER BY clause makes it prefer a record that matches the item criteria if there is one.
Try this
this won't work
Select * From MyTable
Where (GroupID = 1 and ItemID = 2) or (GroupID = 1)
this works
IF EXISTS (SELECT 1 FROM MyTable WHERE GroupID = 1 AND ItemID = 2)
BEGIN
SELECT TOP 1 * FROM MyTable WHERE GroupID = 1 AND ItemID = 2
END
ELSE
BEGIN
SELECT TOP 1 * FROM MyTable WHERE GroupID = 1
END
replace MyTable with the name of your table
replace GroupID and ItemID with the name of your columns
replace number 1 and 2 with whichever value associate with columns you wish to filter
Related
Currently, I have a task: for the presented table, to change students' order by replacing odd and even sequence (example below). There is only one condition, if the number of students is odd, that last number should not be changed. I currently wrote a code like this, however, for me, it seems pretty clumsy. How different and more efficient should this code be written?
CREATE TABLE student (id int, name varchar(128));
INSERT INTO student (id,name) VALUES
(1,'Aurimas'),
(2,'Darius'),
(3,'Eligijus'),
(4,'Giedrius'),
(5,'Justinas');
SELECT CASE
WHEN mod((SELECT id FROM student ORDER BY id DESC LIMIT 1),2) = 0 THEN
CASE
WHEN mod(id, 2) = 0 THEN id-1
ELSE id=id+1
END
ELSE
CASE
WHEN mod(id, 2) = 0 AND id <> (SELECT id FROM student ORDER BY id DESC LIMIT 1) THEN id-1
WHEN mod(id, 2) = 1 AND id <> (SELECT id FROM student ORDER BY id DESC LIMIT 1) THEN id+1
ELSE id
END
END AS new_id, name
FROM student
ORDER BY new_id ASC;
I have this:
id name
1 Aurimas
2 Darius
3 Eligijus
4 Giedrius
5 Justinas
And it should look like this:
id name
1 Darius
2 Aurimas
3 Giedrius
4 Eligijus
5 Justinas
You could group your ids by the value of (id+1) DIV 2. Then all you have to do is swap the minimum id with the maximum id in each pair of rows and make sure you handle the case when there are odd number of rows properly.
Something like this:
set #maxId = (select max(id) from student);
select
if (
#maxId = id and mod(id, 2) != 0,
id,
if (
mod((id+1), 2) = 0,
id+1,
id-1
)
) as id,
name
from student
order by id;
db<>fiddle
I'm not sure how you're defining 'efficient', but how about...
select ROW_NUMBER() OVER (
ORDER BY ceiling(id/2), id desc
) new_id,name from student
The ROW_NUMBER function has been supported in MySQL since version 8.0.
EDIT: I suppose something like will satisfy the quibblers...
WITH cte (id,n) AS (SELECT id, ROW_NUMBER() OVER (ORDER BY id) n FROM student)
SELECT x.name
, ROW_NUMBER() OVER (ORDER BY CEILING(cte.n/2), x.id desc) new_id
FROM student x
JOIN cte
ON cte.id = x.id;
I would recommend to use the below query because
it has many advantages here I am calculating only one max id select but in your case for every case, one select will execute this will reduce that time and only one max id will be used for the odd case
your odd and even operation is the same but in odd you are skipping last record so I added that condition
SET #MAXID = (SELECT MAX(ID) FROM STUDENT);
SELECT
CASE
WHEN MOD(#MAXID,2) != 0 AND ID=#MAXID THEN ID
ELSE CASE WHEN MOD(ID, 2) = 0 THEN ID-1 ELSE ID+1 END
END AS NEW_ID, NAME
FROM STACK_USER.STUDENT
ORDER BY NEW_ID ASC;
I think this would be useful in your case I have checked every condition in my local it will work properly
Screen Shot For Better Understanding:
I'm trying to get values from the database based on two values of my own, the values must match the id of the database
id contactid flag flag_type
-----------------------------------
1 99 Volunteer 1
2 99 Uploaded 2
3 100 Via Import 3
4 100 Volunteer 1
5 100 Uploaded 2
So from here I would want to get the rows with the id's 1 and 2, and ignore the rest of the values. But say for example that the row with the id 2 does not exist the statement would not return any row.
I've tried the following statement, but it doesn't seem to work :
SELECT * FROM docs WHERE id IN (1) AND id IN (2);
You should use OR
SELECT * FROM docs
WHERE id IN (1) OR id IN (2);
or
SELECT * FROM docs
WHERE id = 1
OR id = 2;
or if you need the records for contactid with both id (1,2) then
select * from docs
inner join (
select contactid
from docs
where id IN (1, 2)
having count(distinct id ) = 2
) t on t.contactid = docs.contactid
you need subquery
select id from table_name where contactid in (
select contactid
from table_nae
group by contactid
having count(*)=2
)
subquery will pick only those contactid whose count is two and in condition of main query will help to pick your desired id
If you want the contacts with exactly those flags, you can do:
select contactid
from t
group by contactid
having sum(flag = 1) > 0 and -- has 1
sum(flag = 2) > 0 and -- has 2
sum(flag not in (1, 2)) = 0; -- has nothing else
There are various ways to get the original rows -- using in or exists or join:
select t.*
from t join
(select contactid
from t
group by contactid
having sum(flag = 1) > 0 and -- has 1
sum(flag = 2) > 0 and -- has 2
sum(flag not in (1, 2)) = 0 -- has nothing else
) tt
on t.contactid = tt.contactid;
There is a table users. Based upon 2 column data I need to select rows.
Let say these 2 columns are ID and ID_API.
So while fetching data, I need to search 1st if for a given value exists in ID_API column, then SELECT that row.
Else use ID in WHERE condition.
Here is What is look like
IF EXISTS (SELECT * FROM users WHERE ID_API= '12345')
BEGIN
SELECT * FROM users WHERE ID_API= '12345'
END
ELSE
BEGIN
SELECT * FROM users WHERE ID_= '12345'
END
How to manage it?
In the general case, you can look for rows that have ID_API = 12345, or rows that have ID = 12345 as long as there is no row with ID_API = 12345:
SELECT *
FROM users
WHERE ID_API = '12345' OR
ID = '12345' AND NOT EXISTS (SELECT * FROM users WHERE ID_API = '12345')
In the special case where there is only one row per user, you can do that by searching for either ID_API = 12345 or ID = 12345, then ordering results by ID_API = 12345 descending (since that will return a value of 1 if it is true) and using LIMIT 1 to restrict to 1 row.
SELECT *
FROM users
WHERE ID_API = '12345' OR ID = '12345'
ORDER BY ID_API = '12345' DESC
LIMIT 1
In mysql - table like this:
ID Name Value
1 Color Blue
1 Weight 50
1 Type Fruit
2 Color Red
2 Weight 40
3 Color Yellow
I want to get a count of distinct ID's that have a name/characteristic of 'Type' and a distinct count of ID's that don't. The first one (those that do) is easy since it's defined, but if I do a select count(distinct ID) where name <> 'type' - ID 1 will still be part of that count as it has other rows/attributes that <> 'type'.
In this example - the desired result for distinct count = 'type' would be 1 (ID 1) and for distinct count <> 'type' would be 2 (ID's 2 & 3).
Thanks in advance.
This is similar to SQL Query User has one record in the table but not another one
You can select where the id is not in a subquery looking for ids that have type
select count(id) from table where id not in (select id from table where name = 'type')
group by id
for this particular task you can use:
select count(distinct ID) from table
where ID in (select ID from table where name='type') --- this will give you count of IDs where type exists
select count(distinct ID) from table
where ID not in (select ID from table where name='type') -- this will give you count of IDs without type
SELECT id FROM test GROUP BY id HAVING
CONCAT(",",CONCAT(GROUP_CONCAT(name), ","))
NOT LIKE '%,Type,%'
will give you all ids without Type: http://sqlfiddle.com/#!2/30837/1
(Concat with , ensures, that you are not matching XType by accident.)
while
SELECT COUNT(id) AS count, GROUP_CONCAT(id) AS ids
FROM(SELECT id, count(name) as count FROM test
GROUP BY id HAVING CONCAT(",",CONCAT(GROUP_CONCAT(name), ","))
NOT LIKE '%,Type,%') as temp;
will give you the desired count: http://sqlfiddle.com/#!2/30837/9
SELECT CASE
WHEN Name='Type' THEN 'Type'
ELSE 'Non-Type'
END Name
,ID
,COUNT(ID)
FROM Stuff
GROUP BY
CASE
WHEN Name='Type' THEN 'Type'
ELSE 'Non-Type'
END
,ID
See SQLFiddle
I would like to select multiple values from a single column in a database table that equal to a number of values. I want all these values to match otherwise it should return no rows. I do not want to use "IN" as that is equal to "OR".
The following is a basic mockup of what it should do but it needs to be dynamic as I wish to use it with a PDO statement. If the database only contains id's 1 and 2 it should fail ie return no rows.
SELECT
id
FROM
reports
WHERE
id=1 AND id=2 AND id=3
I have the current code as follow which is incorrectly returning zero rows:
SELECT id,title
FROM reports
WHERE id IN (1,2)
GROUP BY title
HAVING COUNT(DISTINCT id) = 2
My current table structure is as follows:
http://www.sqlfiddle.com/#!2/ce4aa/1
You have to use HAVING COUNT(id) = 3 to ensure that the selected rows have all the three id's. Something like:
SELECT *
FROM reports
WHERE id = 1 OR id = 2 OR id = 3 -- Or id IN(1, 2, 3)
GROUP BY SomeOtherField
HAVING COUNT(DISTINCT id) = 3;
Or:
SELECT *
FROM reports
WHERE SomeOtherField IN (SELECT SomeOtherField
FROM reports
WHERE id = 1 or id = 2 -- Or id IN(1, 2, 3)
GROUP BY SomeOtherField
HAVING COUNT(DISTINCT id) = 3
);
Note that: You have to GROUP BY SomeOtherField where SomeOtherField is other field than id because if you GROUP BY id with HAVING COUNT(id) you won't get any records, since COUNT(id) will be always = 1.
Edit: fixed WHERE clause, OR's instead of AND's.
SQL Fiddle Demo