Find identical values from MySQL table from two columns - php

I need to filter only these table rows which have same values in x and y columns.
_______________________________________
|
| x | y | name |
________________________________________
|
| 1 | 2 | A |
|______________________________________
| 2 | 1 | B |
|______________________________________
| 1 | 2 | C |
|_______________________________________
The final result should be that I have A and C result. I need to filter these rows which has identical x and y values.
_______________________________________
|
| x | y | name |
________________________________________
|
| 1 | 2 | A |
|______________________________________
______________________________________
| 1 | 2 | C |
|_______________________________________
I' ve tried this code but I only managed to with one field.
select *
from auto
where x in (
select x
from auto
group by x
having count(*) > 1
);

SELECT t1.*
FROM tablename t1, tablename t2
WHERE t1.x = t2.x
AND t1.y = t2.y
AND t1.primary_key != t2.primary_key

select * from
auto a, ( SELECT x, y, COUNT(*) FROM auto GROUP BY x, y HAVING COUNT(*) > 1 ) b
where a.x = b.x
and a.y = b.y
will mark your other question as duplicate

Related

mysql - Max occurences of a given value in a table

I have a table like this
+-------+-------+-------+-------+
| id | cid | grade |g_point|
+-------+-------+-------+-------+
| 1 | 10 | A+ | 1 |
| 2 | 10 | A+ | 1 |
| 3 | 10 | B | 3 |
| 4 | 11 | A | 2 |
| 5 | 11 | A+ | 1 |
| 6 | 12 | B | 3 |
the column g_point is the values associated to each grade. forexample A+ grade considers highest so I assign the value of A+ is one(highest starts from 1 to 10) and so on. These g_point values are constant. Now what I want to do is I want to show the maximum grade against each course and also if somehow there are only two entries of different grades I want to compare it with the g_point and choose whose value is lower because lower integer value means higher grade. the result should be like this and also sorted from top grade to lower.
+-------+-------+
| cid | grade |
+-------+-------+
| 10 | A+ |
| 11 | A+ |
| 12 | B |
I have tried this query
SELECT coursecodeID AS cid, (SELECT grade
FROM feedback
WHERE coursecodeID = cid
GROUP BY grade
ORDER BY COUNT(*) DESC LIMIT 0,1) AS g
FROM feedback
GROUP BY coursecodeID
but in this query I don't know how can I compare it with g_point value and also the courses is not showing in order(from highest grade to lowest).
NOTE: I want to choose the grade having the maximum number of occurrences per course id. For example here in this table course id 10 has 2 A+ grade so we'll consider A+ and if clash happens like one is A+ and the other is B+, then we'll have to compare it with the g_point
This works, but needs the 'g_point' to alse be returned.
SELECT cid,grade,MIN(g_point)
FROM grades
GROUP BY cid
This is more reliable, as it generates the Grade in the sub-query, and then appends it to the main table.
SELECT cid, (
SELECT grade
FROM grades g2
WHERE g2.cid = g1.cid
ORDER BY g_point
LIMIT 1
) AS grade
FROM grades g1
GROUP BY cid
You can use the following query:
SELECT DISTINCT m1.cid, m1.grade
FROM mytable AS m1
INNER JOIN (
SELECT cid, MIN(g_point) AS maxGrade
FROM mytable
GROUP BY cid ) m2
ON m1.cid = m2.cid AND m1.g_point = m2.maxGrade
The derived table contains the minimum g_point per cid. If you join it back to the original table, then you can get the maximum grade per cid.
Demo here
EDIT:
You can alternatively use a correlated sub-query:
SELECT cid, (SELECT grade
FROM mytable AS m2
WHERE m2.cid = m1.cid
ORDER BY g_point LIMIT 1) AS maxGrade
FROM mytable AS m1
GROUP BY cid
Demo here
EDIT2:
It looks like you want to get the grade having the maximum number of occurrences per cid. In case there are more than one grades sharing this maximum number, then fetch the grade with the lowest g_point.
You can do it using variables:
SELECT cid, grade
FROM (
SELECT cid, grade,
#row_number := IF (#cid <> cid,
IF (#cid := cid, 1, 1),
IF (#cid := cid, #row_number+1, #row_number+1)) AS rn
FROM (
SELECT cid, grade,
COUNT(*) AS cnt,
(SELECT g_point
FROM mytable AS m2
WHERE m1.grade = m2.grade
LIMIT 1) AS g_point
FROM mytable AS m1
GROUP BY cid, grade
) t
CROSS JOIN (SELECT #row_number:=-1, #cid:=-1) AS vars
ORDER BY cid, cnt DESC, g_point
) s
WHERE rn = 1
Demo here
Something to think about...
SELECT * FROM ints;
+---+
| i |
+---+
| 0 |
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
+---+
SELECT i
, CONCAT(CHAR((i/2)+64),IF(MOD(i,2)=1,'+',''))n
FROM ints
WHERE i > 0;
+---+------+
| i | n |
+---+------+
| 1 | A+ |
| 2 | A |
| 3 | B+ |
| 4 | B |
| 5 | C+ |
| 6 | C |
| 7 | D+ |
| 8 | D |
| 9 | E+ |
+---+------+

MySQL SELECT FROM WHERE COUNT

Hi im looking for an MySQL Select that returns only that rows with doubled entries in column xxx
example:
+------+------+------------+--------------------+
| id | name | work_date | daily_typing_pages |
+------+------+------------+--------------------+
| 1 | John | 2007-01-24 | 250 |
| 2 | Ram | 2007-05-27 | 220 |
| 3 | Jack | 2007-05-06 | 170 |
| 4 | Jack | 2007-04-06 | 100 |
| 5 | Jill | 2007-04-06 | 220 |
| 6 | Zara | 2007-06-06 | 300 |
| 7 | Zara | 2007-02-06 | 350 |
+------+------+------------+--------------------+
Got This Table and i want to read out all entries thats name is listed more than once,
my Query is not working cause it just shows entries with two times the name just once
SELECT id, name, COUNT(name) AS count
FROM table_xy
having count(name) > 1;
what i want to have returned:
+------+------+------------+
| id | name | count |
+------+------+------------+
| 3 | Jack | 2 |
| 4 | Jack | 2 |
| 6 | Zara | 2 |
| 7 | Zara | 2 |
+------+------+------------+
Is there a way to get that?
You could use a subquery for your group by:
SELECT x.id, y.name, y.count
FROM table_xy AS x
INNER JOIN
( SELECT Name, COUNT(*) AS count
FROM table_xy
GROUP BY Name
HAVING COUNT(*) > 1
) AS y
ON y.Name = x.Name;
Alternatively you could use a self join with distinct if you don't need the count:
SELECT DISTINCT x.ID, x.Name
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID;
Or a self join with GROUP BY if you do need the count:
SELECT x.ID, x.Name, COUNT(y.ID) + 1 AS count
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID
GROUP BY x.ID, x.Name;
Examples on SQL Fiddle
try this...
SELECT x.ID, x.Name, COUNT(y.ID) + 1 AS count
FROM table_xy AS x
INNER JOIN table_xy AS y
ON x.Name = y.Name
AND x.ID != y.ID
GROUP BY x.ID, x.Name;

MYSQL SELECT rank of user (more than x & less than y)

I'm a bit stuck with a php/Mysql Query. I got 2 tables :
table_users table_ranks
---------------- ------------------------
| id | points | | name | points_needed |
---------------- ------------------------
| 1 | 2 | | lvl0 | 0 |
| 2 | 10 | | lvl1 | 10 |
| 3 | 21 | | lvl2 | 20 |
| 4 | 29 | | lvl3 | 30 |
---------------- ------------------------
I need an ouput like this :
User_1 = lvl0 (because user has 2 points)
User_2 = lvl1 (because user has just reached 10 points)
...
User_4 = lvl2 (because user has not yet reached 30 points)
Think you :)
Regards.
You can do it like this
SELECT
tu.id,
tr.name,
tu.points
FROM table_ranks as tr
LEFT JOIN (SELECT * FROM table_ranks LIMIT 1,69596585953484) as l
ON l.points_needed = (SELECT MIN(points_needed) FROM table_ranks WHERE points_needed > tr.points_needed limit 1)
LEFT OUTER JOIN table_users AS tu ON tu.points >= tr.points_needed AND tu.points < l.points_needed
WHERE tu.id IS NOT NULL
group by tu.id
Fiddle
Output
-------------------------
| id | points | name |
-------------------------
| 1 | lvl0 | 2 |
| 2 | lvl1 | 10 |
| 3 | lvl2 | 21 |
| 4 | lvl2 | 29 |
-------------------------
give this a try, a little bit messy due to table design,
SELECT u.*, r.name
FROM table_users u
INNER JOIN
(
SELECT x.name,
x.points_needed start_point,
COALESCE(y.points_needed - 1, 2000000) end_point
FROM
(
SELECT name, points_needed, #rank:=#rank+1 ranks
FROM table_ranks a, (SELECT #rank:=0) b
ORDER BY points_needed
) x
LEFT JOIN
(
SELECT name, points_needed, #rank1:=#rank1+1 ranks
FROM table_ranks a, (SELECT #rank1:=0) b
ORDER BY points_needed
) y ON x.ranks+1 = y.ranks
) r ON u.points BETWEEN r.start_point AND r.end_point
SQLFiddle Demo

insert incremental values in an insert ... select statement mysql

I am trying to select a number of rows in a table, reverse the values in one column and reinsert them into the table. Here is an example of what I am doing, say I have the following data:
+-------+--------+-------+
| ORDER | X | Y |
+-------+--------+-------+
| 0 | 12 | 5 |
| 1 | 16 | 3 |
| 2 | 19 | 2 |
+-------+--------+-------+
I want to select it and reinsert it into the same table with the ORDER reversed as so:
+--------+--------+-------+
| PORDER | X | Y |
+--------+--------+-------+
| 2 | 12 | 5 |
| 1 | 16 | 3 |
| 0 | 19 | 2 |
+--------+--------+-------+
I am able to duplicate the rows and reinsert them, no problem using an insert ... select like this:
INSERT INTO myTable (porder, x, y) SELECT porder, x, y FROM myTable
but I have had no success reversing the order. I have tried
INSERT INTO myTable (porder, x, y) SELECT (SELECT porder FROM myTable ORDER BY porder DESC), x, y FROM myTable but that throws an error
It would be fine to simply ignore the porder column and insert new values from 0 to the highest number in the sequence (2 in my above example) but I don't know how to add sequential numbers in a multiple-row insert statement in mysql.
I know how to do this with php but I was thinking there must be a more elegant solution in just SQL
If you know the max-value of order, you can simply do (assuming max(order) = 2)
UPDATE `myTable` SET `PORDER` = 2 - `PORDER`
Example:
+--------+------------+
| PORDER | 2 - PORDER |
+--------+------------+
| 0 | 2-0 = 2 |
| 1 | 2-1 = 1 |
| 2 | 2-2 = 0 |
+--------+------------+
try this
INSERT INTO myTable(`porder`, x, y) SELECT (SELECT MAX(`porder`) FROM myTable) - `porder`, x, y FROM myTable

Update all rows of a single column from another table

Here are the my tables;
TableP:
Pname | Psize
x | -
y | -
z | -
g | -
h | -
TableS:
Pname | Pdate | Ptext
x | XX.XX.XXXX | aasdhb
x | XX.XX.XXXX | asdbahsbdhasbdh
y | XX.XX.XXXX | ajsdbajsdba
y | XX.XX.XXXX | asndansjdbasd
x | XX.XX.XXXX | asd
z | XX.XX.XXXX | asdasbdhasb
g | XX.XX.XXXX | asdnjasdja
g | XX.XX.XXXX | asndjsabdas
h | XX.XX.XXXX | asndjand
x | XX.XX.XXXX | asdjasndnaksd
As you can notice, i've added a new column (Psize) which stands for storing TableS.Ptext length.
How can i update Psize with related Ptext length?
Here is the my query which is not work :) (Subquery returns more than 1 row)
UPDATE TableP
set TableP.Psize = (SELECT sum(LENGTH(Ptext)) as length
FROM TableS group by Pname)
where TableP.Pname = TableS.Pname
Thanks in advance.
Try:
UPDATE TableP p
inner join (
SELECT Pname, sum(LENGTH(Ptext)) as length
FROM TableS
group by Pname
) s on p.Pname = s.Pname
set p.Psize = s.length
Another form keeping your subselect:
UPDATE TableP p
set p.Psize = (
SELECT sum(LENGTH(s.Ptext))
FROM TableS s
where s.pname = p.pname
)
where exists ( -- just to keep it consistent
select 1
from tables s
where s.pname = p.pname
);

Categories