I have to build a some complicated mysql query. I have a table with some user informations, with 3 columns: id, id_user, id_campo, valore. So, for example:
1, 1, 1, "Roberto" (where id_campo=1 is for the user name);
2, 2, 1, "Luca";
3, 1, 2, "Windows"; (where id_campo=2 is for used OS);
4, 2, 2, "Linux";
and so on.
Now, I have to select users where: name="Roberto" AND os="Linux", but the same user :
SELECT id_user WHERE (id_campo=1 AND valore="Roberto") OR (id_campo=2 AND valore="Linux").
In this sample case, the query return id_user=1 and id_user=2 but I would obtain no result. How I can modify the query so I can include the condition "the same user" ?
Thanks!
You need to build two "subqueries" and then join them by user id.
SELECT a.id_user
from (
SELECT id_user FROM table
WHERE (id_campo=1 AND valore="Roberto")
) a,
(
SELECT id_user FROM table
WHERE (id_campo=2 AND valore="Linux")
) b
WHERE a.is_user = b.id_user
You have a wrong db design but anyway you can usie an inner join on the same table based on id_user
select a.id_user, a.id_campo, a.valore
from my_table as a
inner join my_table as b on .id_user = b-id_user
where ( a.id_campo = 1 and a.valore ='Roberto')
AND ( b.id_campo = 2 and b.valore ='Linux')
Related
I have 3 tables in a mysql database that I want to query:
courses (id, course_name)
college_courses (id, college_id, course_id, num_of_courses)
student_courses (id, course_id, college_id)
I am trying to pass an array of course ids to the query and a college id. I want to create a result set to show the name of each course (based on the ids I pass), how many courses the college (e.g. id=8) has access to and how many of each course have been assigned to students. I've tried building a query using joins and sub queries. This is what I have right now but the numbers for courses assigned to colleges and students are all wrong:
SELECT
courses.course_name,
COALESCE(SUM(
CASE
WHEN
college_courses.college_id = 8
THEN
college_courses.num_of_courses
ELSE
0
END
), 0) AS total, COUNT(
CASE
WHEN
student_courses.college_id = 8
THEN
student_courses.id
ELSE
0
END
) AS usedCourses
FROM
courses
LEFT JOIN
college_courses
ON college_courses.course_id = courses.id
LEFT JOIN
student_courses
ON student_courses.course_id = courses.id
WHERE
courses.id IN
(
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
)
GROUP BY
courses.courseid
I have one table in MYSQL called enrollments with these fields: id, user, estimated_date.
The values in this case are:
id, user, estimated_date
1, 1, 2015-10-10
2, 1, 2015-10-10
3, 2, 2015-10-20
4, 2, 2015-10-10
I want to select one row per user: the one that has the max(estimated_date). But in case the estimated_date is equal has to select the one that has the max(id). In other words... a group by with ordering by estimated_date and id (in this order).
The output should be:
2, 1, 2015-10-10
3, 2, 2015-10-20
I have this code now:
SELECT * from enrollments m
INNER JOIN
(SELECT user,
max(estimated_date) AS maxdate
FROM enrollments
GROUP BY user
) x ON m.user = x.user
AND m.estimated_date = x.maxdate
Could you help me please? I've been searching a lot but I didn't find anything that fits this case... Thanks!
You don't need an INNER JOIN, just a ORDER by estimated_date DESC, id DESC is enough. Here is your query:
Select * FROM (
SELECT
DISTINCT `id`, `user`, `estimated_date`
FROM
enrollments
ORDER by estimated_date DESC, id DESC
) as X
GROUP BY user
full fiddle here: http://sqlfiddle.com/#!9/31799/3
I have table units in my database. In schema I have fields id, unit_id, group_id, city_id.
For simple I have 3 units:
(1, 1, 1, 1)
(2, 1, 2, 1)
(3, 1, 3, 2)
How can I remove useless groups id, when city id is the same. I have next result:
(1, 1, 1, 1)
(2, 1, 1, 1)
(3, 1, 3, 2)
I know how do this in PHP, but I think 'maybe MySQL has inbuild functions which i don't know' ;)
Regards
if I understand your question correctly you want to all group_id have same value from the same city_id. Basically your first table in question is what you have and the second one is desired result. If that's the case your query could look like this:
UPDATE table1
INNER JOIN (SELECT * FROM table1 GROUP BY city_id) AS tx
ON table1.city_id = tx.city_id
SET table1.group_id = tx.group_id;
Here is the SQL Fiddle to see how it's work.
If you want to completely remove values and to hold only distinct city_id then you can do that with query like this:
DELETE table1 FROM table1
INNER JOIN (SELECT * FROM table1 GROUP BY city_id) AS tx
ON table1.city_id = tx.city_id
WHERE table1.group_id != tx.group_id;
Here is SQL Fiddle for that!
In this case your result table will be without row with id 2...
GL!
If I understand correctly, you want to delete rows where group_id and city_id are equal? If so, it's very simple:
DELETE FROM units WHERE group_id = city_id
Okay, my solution:
UPDATE `ingame_units` INNER JOIN `ingame_groups` g1 ON `ingame_units`.`group_id`=g1.`id` LEFT JOIN `ingame_groups` g2 ON `ingame_units`.`group_id`<>g2.`id` AND g1.`city_id`=g2.`city_id` AND g1.`id`>g2.`id` AND g1.`game_id`=g2.`game_id` SET `ingame_units`.`group_id`=IFNULL(g2.`id`,g1.`id`)
Thanks one man to minus my post and don't try to help me. Regards :)
I have two tables with the same structure. (refer below)
records = id (int, auto increment), name (varchar 250), age (int), address (varchar 250)
backup = id (int), name (varchar 250), age (int), address (varchar 250)
both table contents 3 records. Now, I want to compare those two tables per row by per column of the row and if there's a row that didnt match to the corresponding row on the compared table then produce and error.
table "records" content:
row 1 : column id = 1, column name = name1, column age = 12, column address = USA
row 2 : column id = 2, column name = name2, column age = 17, column address = USA
row 3 : column id = 3, column name = name3, column age = 32, column address = USA
table "backup" content:
row 1 : column id = 1, column name = name1change, column age = 12, column address = USA
row 2 : column id = 2, column name = name2, column age = 17, column address = USA
row 3 : column id = 3, column name = name3, column age = 32, column address = USA
as you can see from the above table contents, in the table "backup row 1, column name" there is a changes, name1 (records table) is changed to name1change (backup table). So when the row 1 of table records is compare to row 1 of table backup and found a difference, it will then get the row number and column name followed by a text of error (refer below)
echo $errorRow . "with" . $errorColumnOfTheErrorRow . "didn't match, there's is changes";
and I want to loop until the end of records with the same process (compare). How to make it? any ideas, help, suggestions and recommendation would be gladly appreciated. Thank you!
so far, what i tried is (refer below)
$sql = "SELECT DISTINCT * FROM (SELECT a.* FROM records a UNION SELECT b.* FROM backup b ) c";
$result = mysqli_query($this->db,$sql);
$sql = "SELECT COUNT(*), id FROM (SELECT DISTINCT * FROM (SELECT a.* FROM records a UNION SELECT b.* FROM backup b ) c ) d GROUP BY id;";
$result = mysqli_query($this->db,$sql);
echo $result;
as above query, im trying to display the unmatched row but sadly, not working.
You can do this is SQL in a nice way:
First step: put all the data together and keep only the distinct (=not the same) rows:
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c
Second step:
Count all records where ID occurs more then 1 time:
SELECT COUNT(*), id
FROM (
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c ) d
GROUP BY id
HAVING COUNT(*)>1;
This will give you the exact ids where the rows are not the same.
Third step:
Get you the rows with the changed data:
SELECT * FROM (
SELECT "current data" AS description,f.* FROM
records f
INNER JOIN (
SELECT id
FROM (
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c ) d
GROUP BY id
HAVING COUNT(*)>1 ) e ON f.id=e.id
UNION
SELECT "backup data" AS description, g.* FROM
records g
INNER JOIN (
SELECT id
FROM (
SELECT DISTINCT *
FROM (
SELECT a.*
FROM records a
UNION
SELECT b.*
FROM backup b ) c ) d
GROUP BY id
HAVING COUNT(*)>1 ) h ON g.id=h.id;
) i ORDER BY id ASC, description ASC;
It is not pretty, but it works :)
I have a table that I use to store some systematically chosen "serial numbers" for each product that is bought...
The problem is, a CSV was uploaded that I believe contained some duplicate "serial numbers", which means that when the application tries to modify a row, it may not be modifying the correct one.
I need to be able to query the database and get all rows that are a double of the serial_number column. It should look something like this:
ID, serial_number, meta1, meta2, meta3
3, 123456, 0, 2, 4
55, 123456, 0, 0, 0
6, 345678, 0, 1, 2
99, 345678, 0, 1, 2
So as you can see, I need to be able to see both the original row and the duplicate row and all of it's columns of data ... this is so I can compare them and determine what data is now inconsistent.
Some versions of MySQL implement in with a subquery very inefficiently. A safe alternative is a join:
SELECT t.*
FROM t join
(select serial_number, count(*) as cnt
from t
group by serial_number
) tsum
on tsum.serial_number = t.serial_number and cnt > 1
order by t.serial_number;
Another alternative is to use an exists clause:
select t.*
from t
where exists (select * from t t2 where t2.serial_number = t.serial_number and t2.id <> t.id)
order by t.serial_number;
Both these queries (as well as the one proposed by #fthiella) are standard SQL. Both would benefit from an index on (serial_number, id).
SELECT *
FROM
yourtable
WHERE
serial_number IN (SELECT serial_number
FROM yourtable
GROUP BY serial_number
HAVING COUNT(*)>1)
ORDER BY
serial_number, id