In MySQL I have three tables:
A:
-----------------
|g_id | txt |
|------|--------|
| 1 | cat |
| 3 | dog |
and
B:
--------------------------
|g_id | txt | txt2 |
|------|---------|--------
| 1 | hat | chat |
| 3 | that | NULL |
| 3 | that | NULL |
and
C:
------------------
|g_id | txt |
|------|---------|
| 1 | hat |
| 1 | mat |
| 3 | that |
My goal is to sum up the txt column of each row across tables A, B, and C grouped by g_id...
So after my query, the expected result would be:
----------------
|g_id | size |
|------|-------|
| 1 | 16 |
| 3 | 15 |
My query fails:
SELECT
g_id,
SUM(length(txt)) + SUM(length(txt2) as size
FROM ((SELECT a.g_id, a.txt FROM a) UNION ALL
(SELECT b.g_id, b.txt, b.txt2 FROM b) UNION ALL
(SELECT c.g_id, c.txt FROM c)
) abc
GROUP BY g_id;
Error: The used SELECT statements have a different number of columns
Use union all instead of join:
SELECT g_id,
SUM(length(txt)) as size
FROM ((SELECT a.g_id, a.txt FROM a) UNION ALL
(SELECT b.g_id, b.txt FROM b) UNION ALL
(SELECT c.g_id, c.txt FROM c)
) abc
GROUP BY g_id;
Related
How to make more rows from the table? How to decompress table in MySQL?
+-----+-----------+
| num | frequency |
+-----+-----------+
| 0 | 3 |
| 1 | 1 |
| 2 | 2 |
| 3 | 1 |
+-----+-----------+
so that it looks like:
+-----+-----------+
| num | frequency |
+-----+-----------+
| 0 | 3 |
| 0 | 3 |
| 0 | 3 |
| 1 | 1 |
| 2 | 2 |
| 2 | 2 |
| 3 | 1 |
+-----+-----------+
I tried:
SELECT num,
ROW_NUMBER() OVER (PARTITION BY num ORDER BY frequency) AS x
FROM numbers
You could use aa join approach:
INSERT INTO yourTable (num, frequency)
SELECT t1.num, t1.frequency
FROM yourTable t1
INNER JOIN (SELECT 1 AS frequency UNION ALL SELECT 2 UNION ALL SELECT 3) t2
ON t2.frequency < t1.frequency;
You may add more frequency vales to the t2 subquery above as needed.
I'm looking to allow for a custom ordering logic through mySQL that allows the following data set:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 1 | A special place | 3 | 10 | |
| 2 | Another title | 5 | 12 | |
| 3 | Words go here | 1 | 15 | |
| 4 | A wonder | 2 | 8 | |
+----+-----------------+------------+-------+--+
To return an order that alternates, row by row, by popularity and then by views, so the return results look like:
+----+-----------------+------------+-------+--+
| ID | item | Popularity | Views | |
+----+-----------------+------------+-------+--+
| 3 | Words go here | 1 | 15 | |
| 2 | Another title | 5 | 12 | |
| 4 | A wonder | 2 | 8 | |
| 1 | A special place | 3 | 10 | |
+----+-----------------+------------+-------+--+
Where you will see the first row returns the 'most popular', the second row returns the most views, the third row returns the second most popular, and the 4th row returns the 2nd most views.
Currently I'm gathering an entire table through mySQL twice, and then merging these results in PHP. This isn't going to cut it when the database is large. Is this possible in mysql at all?
I guess something along these lines could work. Consider the following:
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,x INT NOT NULL
,y INT NOT NULL
);
INSERT INTO my_table VALUES
(1,3,10),
(2,5,12),
(3,1,15),
(4,2, 8)
(5,4, 1);
We can rank x and y in turn, and then arrange those ranks in a single list - so will have x1,y1,x2,y2,etc - but all rows will appear twice; once for the x rank and once for the y rank...
SELECT * FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) n
ORDER BY rank
+----+---+----+------+
| id | x | y | rank |
+----+---+----+------+
| 5 | 4 | 1 | 1 |
| 3 | 1 | 15 | 1 |
| 4 | 2 | 8 | 2 |
| 4 | 2 | 8 | 2 |
| 1 | 3 | 10 | 3 |
| 1 | 3 | 10 | 3 |
| 5 | 4 | 1 | 4 |
| 2 | 5 | 12 | 4 |
| 2 | 5 | 12 | 5 |
| 3 | 1 | 15 | 5 |
+----+---+----+------+
Now we can just grab the lowest rank for each id...
SELECT id
, x
, y
FROM
(
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.x <= a.x GROUP BY a.id )
UNION ALL
( SELECT a.*, COUNT(*) rank FROM my_table a JOIN my_table b ON b.y <= a.y GROUP BY a.id )
) m
GROUP
BY id,x,y
ORDER
BY MIN(rank);
+----+---+----+
| id | x | y |
+----+---+----+
| 3 | 1 | 15 |
| 5 | 4 | 1 |
| 4 | 2 | 8 |
| 1 | 3 | 10 |
| 2 | 5 | 12 |
+----+---+----+
Incidentally, this should be faster with variables - but I cannot make that solution work at present - senior moment, perhaps.
With the following sample data, I want to create a query that can find where item/desc is duplicate and their respective data fields are not mutually exclusive. Meaning... there can be only 1 data value in column for a given combination of item/desc.
Sample table records:
id | item | desc | data1 | data2 | data3
----+-------+-------+-------+-------+-------
1 | 1 | cat | a | |
2 | 1 | cat | | b |
3 | 1 | cat | | e |
4 | 2 | dog | a | |
5 | 2 | dog | | h | f
6 | 3 | apple | k | | m
7 | 3 | worm | a | g | x
8 | 4 | rock | p | | s
9 | 4 | rock | | | s
10 | 4 | rock | | t | z
Expected query result:
item | desc
-------+-------
1 | cat (because of conflict in data2 with b & e)
4 | rock (because of conflict in data3 with s,s & z
This should work:
select distinct
item,
`desc`
from
table
group by item, `desc`
HAVING count(distinct data1) > 1 or count(distinct data2) > 1 or count(distinct data3) > 1
You could do simple count aggregation and HAVING clause to achieve this.
SELECT `item`,
`desc`,
COUNT(`data1`) AS `data1count`,
COUNT(`data2`) AS `data2count`,
COUNT(`data3`) AS `data3count`
FROM table
GROUP BY `item`, `desc`
HAVING `data1count` > 1
OR `data2count` > 1
OR `data3count` > 1
I have the following problem in MySQL 5.5. Here's my table.
Suppose i have a table With 'Names' with columns Rank,NAME and data in table
When i run the query it will give result as
select *from name
Rank | NAME
-------------
1 | A
1 | B
1 | C
2 | D
2 | E
2 | F
3 | G
3 | H
3 | I
Now this is of course a terribly inconvenient way to organize data, but that's how the data happened to come in (and will continue to come in).
I need to be able to throw at it a way with list of NAMES corresponding to their Respective Rank as shown below
Rank | Name | Name | Name
-----------------------------------
1 | A | B | C
2 | D | E | F
3 | G | H | I
I have query like
select
case when rank=1 then name else null end as 1,
case when rank=2 then name else null end as 2,
case when rank=3 then name else null end as 3
from name
The name with same ranks need to be brought and showed in the same row.i cant estimate the last rank will obtained by the student so i cant pass rank values manually by using 'IN' operator.Since the rank values are unpredictable i need to get them in cross tab view dynamically withh respective to their ranks.
I've tried with all kinds of dynamic crosstab-generating queries (yes, I've seen them all), but I don't have Any sucess. Please help me. Thank you!
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(rank INT NOT NULL
,name CHAR(1) NOT NULL
,PRIMARY KEY(rank,name)
);
INSERT INTO my_table VALUES
(1 ,'A'),
(1 ,'B'),
(1 ,'C'),
(2 ,'D'),
(2 ,'E'),
(2 ,'F'),
(3 ,'G'),
(3 ,'H'),
(3 ,'I');
SELECT * FROM my_table;
+------+------+
| rank | name |
+------+------+
| 1 | A |
| 1 | B |
| 1 | C |
| 2 | D |
| 2 | E |
| 2 | F |
| 3 | G |
| 3 | H |
| 3 | I |
+------+------+
SELECT x.*,COUNT(*) subrank FROM my_table x JOIN my_table y ON y.rank = x.rank AND y.name <= x.name GROUP BY x.rank,x.name;
+------+------+---------+
| rank | name | subrank |
+------+------+---------+
| 1 | A | 1 |
| 1 | B | 2 |
| 1 | C | 3 |
| 2 | D | 1 |
| 2 | E | 2 |
| 2 | F | 3 |
| 3 | G | 1 |
| 3 | H | 2 |
| 3 | I | 3 |
+------+------+---------+
SELECT rank
, MAX(CASE WHEN subrank = 1 THEN name END) name1
, MAX(CASE WHEN subrank = 2 THEN name END) name2
, MAX(CASE WHEN subrank = 3 THEN name END) name3
FROM
( SELECT x.*
, COUNT(*) subrank
FROM my_table x
JOIN my_table y
ON y.rank = x.rank
AND y.name <= x.name
GROUP
BY x.rank
, x.name
) a
GROUP
BY rank;
+------+-------+-------+-------+
| rank | name1 | name2 | name3 |
+------+-------+-------+-------+
| 1 | A | B | C |
| 2 | D | E | F |
| 3 | G | H | I |
+------+-------+-------+-------+
i have the following table and I'm hoping to extract all the unique pairs for ex:
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 3 |
| 1 | 6 |
| 1 | 9 |
| 2 | 1 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 4 | 1 |
| 6 | 5 |
+------+------+
the out put should be
+------+------+
| a | b |
+------+------+
| 1 | 2 |
| 1 | 3 |
| 1 | 6 |
| 1 | 9 |
| 2 | 3 |
| 6 | 5 |
+------+------+
Try this:
select least(a, b) as a, greatest(a, b) as b
from table t
group by least(a, b), greatest(a, b);
This could produce output that is not in the original table (such as 5/6 instead of 6/5). If you want to preserve the original order:
select distinct a, b
from table t
where a <= b or
not exists (select 1 from table t2 where t2.b = t.a and t2.a = t.b);
That is, select all pairs where a is less than or equal to b or a is greater than b and no row exists with the values in the other order.
SELECT a,b
FROM tbl //your tableName
GROUP BY a,b
HAVING COUNT(*) > 1
try this my friend
SELECT *
FROM NAMES2
GROUP BY Id,id2
HAVING COUNT(*) > 1;
How about this ?