Given a table data as follows:
id
a1
a2
a3
1
b
300
10
2
c
111
12
3
b
300
10
4
b
300
10
Is there a way to select ONLY THOSE ids of rows where information, which is stored in columns "a1","a2,"a3", differ?
In this case, the output should be:
[1, 2] OR [2, 3] OR [2, 4]
Doesnt matter wether the representative id of "same rows" was taken from the first one, third one or fourth one.
What I have tried:
SELECT id
FROM data
GROUP BY a1, a2, a3;
This ofcourse wont work unless I disable ONLY_GROUP_BY_ALL mode, however I'd rather not disable such feature and turn to alternatives if those exist.
As a joke:
SELECT t1.id, t2.id
FROM data t1
JOIN data t2 ON (t1.a1, t1.a2, t1.a3) <> (t2.a1, t2.a2, t2.a3)
LIMIT 1
If some columns may be NULL then
SELECT t1.id, t2.id
FROM data t1
JOIN data t2 ON NOT ((t1.a1, t1.a2, t1.a3) <=> (t2.a1, t2.a2, t2.a3))
LIMIT 1
Related
MySQL Version: 5.7.36
I'm attempting to minimize the amount of queries I have to execute.
Right now, I'm executing a query similar to this:
SELECT
TABLE 1.column1 as "A",
TABLE 1.column2 as "B"
FROM
TABLE 1
WHERE
CONDITION
I can obtain the results I need from this query, however I would also like to obtain the count of what type of values show up in the same query.
For example, if the following query retrieves this table
A B
- -
1 a
1 b
1 c
2 d
3 e
4 f
4 g
I would also like to, for each row, obtain the count of all rows retrieved with its column "A" that matches its value.
Would it be more efficient to execute another query to get that result or can I modify my obtaining query to get this statistic?
Desired result:
A B C
- - -
1 a 3 # 3 rows with "1" in Column "A"
1 b 3
1 c 3
2 d 1
3 e 1
4 f 2
4 g 2
UPDATE:
The closest query I could find goes like this:
SELECT
TABLE 1.column1 as "A",
COUNT(TABLE 1.column1)
FROM
TABLE 1
WHERE
TABLE 1.column1 = "foo"
GROUP BY
TABLE 1.column1
Results in this:
A B C
- - -
1 a 3
2 d 1
3 e 1
4 f 2
However, it removes any other rows with the same value in column "A". Even if it has different values in column "B". I would like to have all rows present in my SQL query with its corresponding row count.
The next closest query I found goes like this:
SELECT
TABLE 1.column1 as "A",
COUNT(TABLE 1.column1)
FROM
TABLE 1
WHERE
TABLE 1.column1 = "foo"
GROUP BY
TABLE 1.column2
Results in this:
A B C
- - -
1 a 1
1 b 1
1 c 1
2 d 1
3 e 1
4 f 1
4 g 1
Which also isn't achieving the desired result.
You have to join with the subquery that gets the counts.
SELECT t1.column1 AS A, t1.column2 AS B, t2.count
FROM Table1 AS t1
JOIN (
SELECT column1 AS A, COUNT(*) AS count
FROM Table1
GROUP BY column1
) AS t2 ON t1.A = t2.A
SELECT
c,
COUNT(*) OVER (PARTITION BY c)
FROM t
ORDER BY c
I need a sql query which will fetch me the count of unique possible combination of a value a to b of col3 based on the col2 value.
Here in the below table the value a to b is there twice(2 to 3 for col1-1 and 2 to 3 for col1-2).Similarly I need the count of such possible a to b fields as they appear successively in the table(which we can identify from col2-2,3)
I have the following table:
col1 col2 col3
1 2 a
1 3 b
1 4 c
2 2 a
2 3 b
2 4 c
Output:
f1 f2 count
a b 2
b c 2
Here col1+col2 is the primary key and the query should be generic for n no of possible successive combination.
As I was looking into possibilities of finding the solution to my problem, I got one by myself...
Below is the query to get the desired output which I wanted, was pretty straight forward.
select a.col3 f1,
b.col3 f2,
count(*) count
from testTable b,testTable a
where
a.col2 = b.col2 -1
and a.col1 = b.col1
group by ev1,ev2;
Background:
Given table t1 with fields A, B (and others):
DROP TEMPORARY TABLE IF EXISTS t1;
CREATE TEMPORARY TABLE t1 (ID INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, A varchar(255), B int, C varchar(40));
INSERT INTO t1 (A, B, C)
SELECT 'AA', 11, 100
UNION ALL
SELECT 'BB', 12, 200
UNION ALL
SELECT 'BB', 12, 201
UNION ALL
SELECT 'AA', 12, 300
UNION ALL
SELECT 'AA', 11, 101;
-- ID A B C
-- 1 AA 11 100
-- 2 BB 12 200
-- 3 BB 12 201
-- 4 AA 12 300
-- 5 AA 11 101
GOAL: For a given combination of A and B, examine how many rows there are in t1, and then list all those rows (to understand what is same and what is different between those rows).
(Finally, but beyond the scope of this question, will be writing queries to process some of the older rows, that are determined to be "obsolete" (replaced by the most recent row with given A and B). Its not safe to do so for ALL combinations of A and B, at this time. A definitive answer on "what combinations of A and B are safe to delete old version of" is not available to me - this is a legacy table which has associated with it many GBs of external files, most of which are no longer relevant to anyone. All those files have been backed up; I need to make a conservative proposal as to which files to remove, and how I determined those files.)
I've made temp table t2 with all distinct combinations of A and B (plus an ID, and a count of how many rows of each combo):
DROP TEMPORARY TABLE IF EXISTS t2;
CREATE TEMPORARY TABLE t2 (ID INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, A varchar(255), B int)
SELECT COUNT(1) As Cnt, A, B FROM t1
GROUP BY A, B
ORDER BY Cnt DESC;
SELECT * FROM t2
-- ID Cnt A B
-- 1 2 AA 11
-- 2 2 BB 12
-- 3 1 AA 12
The query that I am having trouble writing:
In the actual data, there are hundreds of rows for some combinations. I am most interested in the combinations that have a high count, so I attempt to dump the rows of t1, based on the first row of t2:
SELECT * FROM t1
WHERE A=
(SELECT A from t2 LIMIT 1 OFFSET 0) AND
B=
(SELECT B from t2 LIMIT 1 OFFSET 0);
This gives error:
Error Code: 1137. Can't reopen table: 't2'
I presume that I should refer to the row I want from t2:
(SELECT A, B from t2 LIMIT 1 OFFSET 0)
And then make a nested query that uses this row twice, in the two places where columns A and B are used. I am stuck on how to write this query. The basic idea in my head is:
SELECT * FROM t1
WHERE A=t3.A AND B=t3.B IN
(SELECT A, B from t2 LIMIT 1 OFFSET 0) AS t3;
(which is not valid SQL)
NOTE: "OFFSET 0" is there because then I will change to other offset values, to examine other A-B combos.
The goal is to see response:
-- ID A B C
-- 1 AA 11 100
-- 5 AA 11 101
Or maybe this can be done with a JOIN, but I'm not sure how to do a JOIN using just one row of t2.
You can do something like this:
SELECT t1.*
FROM t1
JOIN ( SELECT t2.A, t2.B
FROM t2
ORDER BY t2.A, t2.B
LIMIT 1 OFFSET 0
) t3
WHERE t3.A = t1.A
AND t3.B = t1.B
Without an ORDER BY clause, MySQL is free to return any row. We need to add the ORDER BY to make the result deterministic.
I'd like to apply a simple transformation to a group of common rows, if one row meets a particular criteria.
For example, in the following data, I'd like to add 1 to each Value for any ID that has a value of 0... for all of his values such that this data
Value ID
2 1
3 1
0 2
1 2
would transform to this...
Value ID
2 1
3 1
1 2
2 2
Any help is greatly appreciated!
Arrg. This is MySQL. You can do this with a join:
update t join
(select distinct t2.id
from t t2
where t2.value = 0
) t2
on t2.id = t.id
set t.value = t.value + 1;
There is a table "T" that contains data as shown below:
A B
---------
3 5
4 6
7 10
8 5
9 12
3 6
3 7
8 7
Assuming a given input set of {3,8} as values for A, how to retrieve all distinct values of B for which all values in the input set has an entry?
B
---
5
7
EDIT: I think the question is not clear enough. I want values in B which have a record with all values in the given set as a value for column A. So, B=6 will not be included since there is no record with A=8 and B=6. Hope this makes it clear!
SELECT DISTINCT B
FROM my_table WHERE A IN (3,8)
EDIT:
SELECT B FROM AB WHERE A = 3
INTERSECT
SELECT B FROM AB WHERE A = 8
INTERSECT give you the rows which occurs in both resultsets.
2nd EDIT:
SELECT B,COUNT(B)
FROM AB WHERE A IN (3,8)
GROUP BY B
HAVING COUNT(B) = 2
You should however modify this in two places: in IN arguments and on the end, in COUNT(B) = ?. ? should be equal the number of the arguments. I hope this will help.
3rd EDIT:
SELECT B,COUNT(B)
FROM
(
SELECT DISTINCT A, B FROM AB
) x
WHERE A IN (3,8)
GROUP BY B
HAVING COUNT(B) = 2
This will avoid the duplicate entries problem.
Basically, you can create two subqueries where you filter out only the rows that are candidates for matching (i.e. A is either 3 or 8). Then join those rows with each other on the value of B, and any matching rows will be what you're looking for. I'm not 100% certain of the syntax for MySQL, but I believe this will work:
SELECT *
FROM (SELECT * FROM T WHERE A = 3) t3
INNER JOIN (SELECT * FROM T WHERE A = 8) t8 ON t3.B = t8.B