Is there a way in SQL (MySQL) to do a "round robin" ORDER BY on a particular field?
As an example, I would like to take a table such as this one:
+-------+------+
| group | name |
+-------+------+
| 1 | A |
| 1 | B |
| 1 | C |
| 2 | D |
| 2 | E |
| 2 | F |
| 3 | G |
| 3 | H |
| 3 | I |
+-------+------+
And run a query that produces results in this order:
+-------+------+
| group | name |
+-------+------+
| 1 | A |
| 2 | D |
| 3 | G |
| 1 | B |
| 2 | E |
| 3 | H |
| 1 | C |
| 2 | F |
| 3 | I |
+-------+------+
Note that the table may have many rows, so I can't do the ordering in the application. (I'd obviously have a LIMIT clause as well in the query).
I'd try something like:
SET #counter = 0;
SELECT (#counter:=#counter+1)%3 as rr, grp, name FROM table ORDER by rr, grp
What you can do is create a temporary column in which you create sets to give you something like this:
+-------+------+-----+
| group | name | tmp |
+-------+------+-----+
| 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 |
+-------+------+-----+
To learn how to create the sets, have a look at this question/answer.
Then its a simple
ORDER BY tmp, group, name
You can use MySQL variables to do this.
SELECT grp, name, #row:=#row+1 from table, (SELECT #row:=0) r ORDER BY (#row % 3);
+------+------+--------------+
| grp | name | #row:=#row+1 |
+------+------+--------------+
| 1 | A | 1 |
| 2 | D | 4 |
| 3 | G | 7 |
| 1 | B | 2 |
| 2 | E | 5 |
| 3 | H | 8 |
| 1 | C | 3 |
| 2 | F | 6 |
| 3 | I | 9 |
+------+------+--------------+
Related
I have a table that cotains the id of the students, the course name and the course level.
+----+--------+-------+
| Id | Course | Level |
+----+--------+-------+
| 1 | A | 1 |
| 2 | A | 1 |
| 1 | B | 1 |
| 3 | B | 1 |
| 4 | C | 2 |
+----+--------+-------+
From this, I want to know the percentage each course covers by level.
Like in the below table:
+-------+--------+----------------+
| Level | Course | Count_by_level |
+-------+--------+----------------+
| 1 | A | 50% |
| 1 | A | 50% |
| 1 | B | 50% |
| 1 | B | 50% |
| 2 | C | 100% |
+-------+--------+----------------+
How can I do this using SQL?
SQL DEMO
SELECT S.[Id] , S.[Course], S.[Level], T.ctotal,
100.0 / T.ctotal
FROM students S
JOIN ( SELECT [Course], COUNT(*) as ctotal
FROM students
GROUP BY [Course]
) T
ON S.[Course] = T.[Course]
OUTPUT
| Id | Course | Level | ctotal | |
|----|--------|-------|--------|-----|
| 1 | A | 1 | 2 | 50 |
| 2 | A | 1 | 2 | 50 |
| 1 | B | 1 | 2 | 50 |
| 3 | B | 1 | 2 | 50 |
| 4 | C | 2 | 1 | 100 |
Just another option using the window functions (assuming 2012+)
Example
Select [Level]
,[Course]
,Pct = 100.0 / sum(1) over (partition by [Level],[Course])
From YourTable
Returns
Level Course Pct
1 A 50.000000
1 A 50.000000
1 B 50.000000
1 B 50.000000
2 C 100.000000
How to get count of combinations from database?
I have to database tables and want to get the count of combinations. Does anybody know how to put this in a database query, therefore I haven't a db request for each trip?
Trips
| ID | Driver | Date |
|----|--------|------------|
| 1 | A | 2015-12-15 |
| 2 | A | 2015-12-16 |
| 3 | B | 2015-12-17 |
| 4 | A | 2015-12-18 |
| 5 | A | 2015-12-19 |
Passengers
| ID | PassengerID | TripID |
|----|-------------|--------|
| 1 | B | 1 |
| 2 | C | 1 |
| 3 | D | 1 |
| 4 | B | 2 |
| 5 | D | 2 |
| 6 | A | 3 |
| 7 | B | 4 |
| 8 | D | 4 |
| 9 | B | 5 |
| 10 | C | 5 |
Expected result
| Driver | B-C-D | B-D | A | B-C |
|--------|-------|-----|---|-----|
| A | 1 | 2 | - | 1 |
| B | - | - | 1 | - |
Alternative
| Driver | Passengers | Count |
|--------|------------|-------|
| A | B-C-D | 1 |
| A | B-D | 2 |
| A | B-C | 1 |
| B | A | 1 |
Has anybody an idea?
Thanks a lot!
Try this:
SELECT Driver, Passengers, COUNT(*) AS `Count`
FROM (
SELECT t.ID, t.Driver,
GROUP_CONCAT(p.PassengerID
ORDER BY p.PassengerID
SEPARATOR '-') AS Passengers
FROM Trips AS t
INNER JOIN Passengers AS p ON t.ID = p.TripID
GROUP BY t.ID, t.Driver) AS t
GROUP BY Driver, Passengers
The above query will produce the alternative result set. The other result set can only be achieved using dynamic sql.
Demo here
I'm migrating a database from one application to another. In the first one I've two tables: proyectos and presupuestos. A row in 'proyectos' can have one or more rows in 'presupuestos'.
The new application has a field in presupuestos that is made concatenating the code of the proyect with the number of 'presupuesto' of this proyect. That's what I don't know how to do it.
My tables are like:
Proyectos:
+--------------+------------------+
| proyectos_id | proyectos_codigo |
+--------------+------------------+
| 1 | E+-00001 |
| 2 | E+-00002 |
| 3 | E+-00003 |
| 4 | E+-00004 |
| 5 | E+-00005 |
+--------------+------------------+
Presupuestos:
+-----------------+--------------+
| presupuestos_id | proyectos_id |
+-----------------+--------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 2 |
| 5 | 3 |
| 6 | 3 |
| 7 | 3 |
| 8 | 4 |
| 9 | 4 |
| 10 | 5 |
+-----------------+--------------+
I've tried with this query:
select presupuestos_id, p.proyectos_id, concat(pr.proyectos_codigo,'_1') from presupuestos p join proyectos pr on p.proyectos_id = pr.proyectos_id
Which result is:
+-----------------+--------------+----------------------------------+
| presupuestos_id | proyectos_id | concat(pr.proyectos_codigo,'_1') |
+-----------------+--------------+----------------------------------+
| 1 | 1 | E+-00001_1 |
| 2 | 1 | E+-00001_1 |
| 3 | 1 | E+-00001_1 |
| 4 | 2 | E+-00002_1 |
| 5 | 3 | E+-00003_1 |
| 6 | 3 | E+-00003_1 |
| 7 | 3 | E+-00003_1 |
| 8 | 4 | E+-00004_1 |
| 9 | 4 | E+-00004_1 |
| 10 | 5 | E+-00005_1 |
+-----------------+--------------+----------------------------------+
But obviusly, It doesn't what I want. My desired result is:
+-----------------+--------------+----------------------------------+
| presupuestos_id | proyectos_id | some code |
+-----------------+--------------+----------------------------------+
| 1 | 1 | E+-00001_1 |
| 2 | 1 | E+-00001_2 |
| 3 | 1 | E+-00001_3 |
| 4 | 2 | E+-00002_1 |
| 5 | 3 | E+-00003_1 |
| 6 | 3 | E+-00003_2 |
| 7 | 3 | E+-00003_3 |
| 8 | 4 | E+-00004_1 |
| 9 | 4 | E+-00004_2 |
| 10 | 5 | E+-00005_1 |
+-----------------+--------------+----------------------------------+
Try this :
SELECT presupuestos_id, p.proyectos_id,
CONCAT(pr.proyectos_codigo,'_',
(CASE p.proyectos_id
WHEN #p_id
THEN #rownumber := #rownumber + 1
ELSE #rownumber := 1 AND #p_id := p.proyectos_id END)
)AS result
FROM presupuestos p
JOIN proyectos pr ON p.proyectos_id = pr.proyectos_id
JOIN (SELECT #rownumber:=0, #p_id:='') AS t
This should do what you want, although the answer by RubahMalam looks better... :
SELECT a.presupuestos_id, a.proyectos_id, concat(p.proyectos_codigo,'_', count(*)) as "Some code"
FROM (
SELECT pr.presupuestos_id, pr.proyectos_id
FROM Presupuestos pr JOIN Proyectos p ON pr.proyectos_id = p.proyectos_id
) a
JOIN (
SELECT pr.presupuestos_id, pr.proyectos_id
FROM Presupuestos pr JOIN Proyectos p ON pr.proyectos_id = p.proyectos_id
) b
ON a.proyectos_id = b.proyectos_id AND a.presupuestos_id >= b.presupuestos_id
JOIN Proyectos p ON a.proyectos_id = p.proyectos_id
GROUP BY a.proyectos_id, a.presupuestos_id, p.proyectos_codigo
Sample SQL Fiddle
I have searched and gone through the available topics similar to mine. But, failed to find that satisfies my requirements. Hence, posting it here.
I have four tables as follows:
"Organization" table:
--------------------------------
| org_id | org_name |
| 1 | A |
| 2 | B |
| 3 | C |
"Members" table:
----------------------------------------------
| mem_id | mem_name | org_id |
| 1 | mem1 | 1 |
| 2 | mem2 | 1 |
| 3 | mem3 | 2 |
| 4 | mem4 | 3 |
"Resource" table:
--------------------------------
| res_id | res_name |
| 1 | resource1 |
| 2 | resource2 |
| 3 | resource3 |
| 4 | resource4 |
"member-resource" table:
--------------------------------------------
| sl_no | mem_id | res_id |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 4 | 3 |
| 5 | 3 | 4 |
| 6 | 2 | 3 |
| 7 | 4 | 3 |
I want to find out the total number of distinct resources according to organizations. Expected output is as follows:
| org_name | Total Resources |
| A | 3 |
| B | 1 |
| C | 1 |
I also want to find out the total number of shared resources according to organizations. Expected output is as follows:
| org_name | Shared Resources |
| A | 1 |
| B | 0 |
| C | 1 |
Any help in this regard will highly be appreciated.
Regards.
It is much simpler than you think, particularly because you don't even need the resource table:
SELECT o.org_name, COUNT(DISTINCT mr.res_id) TotalResources
FROM member_resource mr
JOIN members m ON mr.mem_id = m.mem_id
JOIN organization o ON m.org_id = o.org_id
GROUP BY o.org_id
Output:
| ORG_NAME | TOTALRESOURCES |
|----------|----------------|
| A | 3 |
| B | 1 |
| C | 1 |
Fiddle here.
Try this query below.
SELECT org_name, COUNT(DISTINCT res_id)
FROM organization, members, member-resource
WHERE members.mem_id = member-resource.mem_id
AND organization.org_id = members.org_id
GROUP BY org_id, org_name
Image we have a table like this:
table1
+----------+----------+--------+------------+
| position | epoc | name | value |
+----------+----------+--------+------------+
| 1 | 1 | A | v01 |
| 1 | 1 | B | v02 |
| 1 | 1 | C | v03 |
| 1 | 2 | A | v04 |
| 1 | 2 | B | v05 |
| 1 | 2 | C | v06 |
| 1 | 3 | A | v07 |
| 1 | 3 | B | v08 |
| 1 | 3 | C | v09 |
| 1 | 4 | A | v10 |
| 1 | 4 | B | v11 |
| 1 | 4 | C | v12 |
| 2 | 5 | A | v13 |
| 2 | 5 | B | v14 |
| 2 | 5 | C | v15 |
| 2 | 6 | A | v16 |
| 2 | 6 | B | v17 |
| 2 | 6 | C | v18 |
| 2 | 7 | A | v19 |
| 2 | 7 | B | v20 |
| 2 | 7 | C | v21 |
| 2 | 8 | A | v22 |
| 2 | 8 | B | v23 |
| 2 | 8 | C | v24 |
+----------+----------+--------+------------+
I want to be able to get this table:
table2
+----------+--------------------+
| position | value |
+----------+--------------------+
| 1 | v01,v02,v04,v05 |
| 2 | v13,v14,v16,v17 |
+----------+--------------------+
the conditions are:
JUST the "value" of rows with "name" A OR B;
JUST "epocs" that are the first 2 unique results in "position" (epoc 3,4,7,8 are discarded)
GROUP by table1 position (for each position I want the concat of the values that match previous conditions)
This might be what you are looking for:
select position,
group_concat(value order by overall_row_num) value
from
(
select position,
name,
value,
epoc,
#num := if(#position = `position`, #num + 1, 1) as group_row_number,
#position := `position` as dummy,
overall_row_num
from
(
select position, name,
epoc,
value,
#rn:=#rn+1 overall_row_num
from t1, (SELECT #rn:=0) r
where name in ('A', 'B')
order by position, epoc
) x
order by overall_row_num
) x1
where group_row_number <= 4
group by position
See SQL Fiddle with demo