I need to put a record at last of the result set ordered by a column field in ascending order.
LIKE:
SELECT "#TOTAL"...
Which is a user-defined column value.
Here's what I am trying to do:
SELECT cnt.name as Client, NULL, NULL, NULL, ', #COL_SUM, '
FROM
task as tsk
LEFT JOIN client cnt
ON tsk.client_id = cnt.id
GROUP BY tsk.client_id
UNION ALL
SELECT "#TOTAL#",NULL,NULL,NULL, ', #COL_SUM, '
FROM task as tsk
ORDER BY Client ASC
This returns result set as:
Client | ... | Admin | Intern | ..
---------------------------------------
#TOTAL# | ... | 4 | 2 | .. <-- this row here is grand total
A | ... | 1 | | ..
B | ... | 1 | 1 | ..
C | ... | 2 | 1 | ..
I want the #TOTAL# row to be at last.
What character, except z, comes at last in alphabetical order?
Just add your condition to the ORDER BY clause:
order by Client = '#TOTAL#', Client
You could add another constant column to the individual queries that indicate if it's a total or a regular row and order by that first.
SELECT *
FROM (SELECT 0 first_order,
cnt.name client,
...
UNION ALL
SELECT 1 first_order,
'#TOTAL#' client,
...) x
ORDER BY first_order,
client;
Try this variant of code.
For mysql:
SELECT 0 as [OrderBy], cnt.name as Client, NULL, NULL, NULL, ', #COL_SUM, '
FROM
task as tsk
LEFT JOIN client cnt
ON tsk.client_id = cnt.id
GROUP BY tsk.client_id
UNION ALL
SELECT 1 , "#TOTAL#",NULL,NULL,NULL, ', #COL_SUM, '
FROM task as tsk
ORDER BY [ORDERBY], cLIENT_ID
For sql server
SELECT * FROM (
SELECT TOP 100 PERCENT cnt.name as Client, NULL, NULL, NULL, ', #COL_SUM, '
FROM
task as tsk
LEFT JOIN client cnt
ON tsk.client_id = cnt.id
GROUP BY tsk.client_id
ORDER BY TSK.CLIENT_ID) AS DATA
UNION ALL
SELECT "#TOTAL#",NULL,NULL,NULL, ', #COL_SUM, '
FROM task as tsk
Since you are not able to apply order by in the first part of your query, so there is a method to do so, top 100 percent, and you can apply order by clause in your inner query or sub query.
Hope this helps.
Related
Table: statistics
id | user | Message
----------------------
1 | user1 |message1
2 | user2 |message2
3 | user1 |message3
I am able to find the count of messages sent by each user using this query.
select user, count(*) from statistics group by user;
How to show message column data along with the count? For example
user | count | message
------------------------
user1| 2 |message1
|message3
user2| 1 |message2
You seem to want to show Count by user, which message sent by user.
If your mysql version didn't support window functions, you can do subquery to make row_number in select subquery, then only display rn=1 users and count
CREATE TABLE T(
id INT,
user VARCHAR(50),
Message VARCHAR(100)
);
INSERT INTO T VALUES(1,'user1' ,'message1');
INSERT INTO T VALUES(2,'user2' ,'message2');
INSERT INTO T VALUES(3,'user1' ,'message3');
Query 1:
SELECT (case when rn = 1 then user else '' end) 'users',
(case when rn = 1 then cnt else '' end) 'count',
message
FROM (
select
t1.user,
t2.cnt,
t1.message,
(SELECT COUNT(*) from t tt WHERE tt.user = t1.user and t1.id >= tt.id) rn
from T t1
join (
select user, count(*) cnt
from T
group by user
) t2 on t1.user = t2.user
) t1
order by user,message
Results:
| users | count | message |
|-------|-------|----------|
| user1 | 2 | message1 |
| | | message3 |
| user2 | 1 | message2 |
select user, count(*) as 'total' , group_concat(message) from statistics group by user;
You could join the result of your group by with the full table (or vice versa)?
Or, depending on what you want, you could use group_concat() using \n as separator.
Use Group_concat
select user, count(0) as ct,group_concat(Message) from statistics group by user;
This will give you message in csv format
NOTE: GROUP_CONCAT has size limit of 1024 characters by default in mysql.
For UTF it goes to 1024/3 and utfmb4 255(1024/4).
You can use group_concat_max_len global variable to set its max length as per need but take into account memory considerations on production environment
SET group_concat_max_len=100000000
Update:
You can use any separator in group_concat
Group_concat(Message SEPARATOR '----')
Try grouping with self-join:
select s1.user, s2.cnt, s1.message
from statistics s1
join (
select user, count(*) cnt
from statistics
group by user
) s2 on s1.user = s2.user
SELECT DISTINCT * FROM ( SELECT hostname, table2.user-id, table2.user-team from
INNER JOIN table2 on table1.id = table2.id)
So at the moment my SQL query outputs this:
hostname user-id user-team
a 1 alpha
a 2 beta
b 3 beta
c 4 alpha
c 1 null
c 3 alpha
but what I want is something like this:
hostname user-id user-team
a 1, 2 alpha, beta
b 3 beta
c 4, 1, 3 alpha
I'm trying to use a GROUP BY hostname statement at the end of my query, and a GROUP_CONCAT(DISTINCT user_id SEPARATOR ', '), GROUP_CONCAT(DISTINCT user_team SEPARATOR ', '),
But this then only returns the first hostname result and all the values possible for the user-id and team-id. I feel like I'm close, but I can't quite get it. Any help?
(At present it returns)
hostname user-id user-team
a 1,2,3,4 alpha, beta
with this as the SQL query
SELECT DISTINCT *
FROM ( SELECT hostname,
GROUP_CONCAT(DISTINCT table2.user-id SEPARATOR(', '),
GROUP_CONCAT(DISTINCT table2.team-id SEPARATOR(', ')
from table1
INNER JOIN table2 on table1.id = table2.id)
GROUP BY hostname
Although the queries arean't 100% accurate, that is the logic in them (they just contain far more columns in the real world problem I have.)
I think you miss the GROUP BY
SQL DEMO
SELECT hostname,
GROUP_CONCAT(DISTINCT user_id SEPARATOR ', ') as users,
GROUP_CONCAT(DISTINCT user_team SEPARATOR ', ') as teams
FROM Table1
GROUP BY hostname
OUTPUT
| hostname | users | teams |
|----------|---------|-------------|
| a | 1, 2 | alpha, beta |
| b | 3 | beta |
| c | 4, 1, 3 | alpha |
EDIT: After you edit your question, the problem was you put the GROUP BY outside of the subquery
I have two tables in relation connected with primary and foreign key.
In the first table I have a server list with attributes (id, name, ip,...).
In the second table I want to insert in future Update-Informations (id, server_id, last_update, next_update,...).
Now I want to show in my GUI the Server-Attrinbutes from first table and only the last entry from second table for each server with equals server_id.
Table 1:
id
name
ip
description
.
.
Table 2:
id
server_id
last_update
next_update
.
.
Here is a short example how I already tried it:
select s.id, s.name, sp.last_update, sp.next_update
from server s
left join (select * from server_updates order by server_id desc) sp
on sp.server_id = s.id
I already tried it with the statement LIMIT 1
select s.id, s.name, sp.last_update, sp.next_update
from server s
left join (select * from server_updates order by server_id desc limit 1) sp
on sp.server_id = s.id
Also I have tried to use DISTINCT
select DISTINCT s.id, s.name, sp.last_update, sp.next_update
from server s
left join (select * from server_updates order by server_id desc limit 1)
But I always got all entrys from second table
+------------+-----------------+---------------+------------+------------+
| Server0101 | Server0101_name | Server0101_ip | 2017-09-20 | 2017-10-20 |
| Server0101 | Server0101_name | Server0101_ip | 2017-10-20 | 2017-11-20 |
| Server0102 | Server0102_name | Server0102_ip | 2017-05-01 | 2017-06-01 |
I just want one row from second table for each ID from first table.
Of course I can implement this in my JAVA-Code, but can you please tell me how to do this in MySQL.
Have you tried the below one?
select s.id, s.name, sp.last_update, sp.next_update
from server s
left join (select * from server_updates where server_id =s.id order by server_id desc limit 1) sp
on sp.server_id = s.id
I have a MySQL table where I'm trying to find a person by his full name. The problem is that first and last name are stored on two separate rows in the table as shown here:
+-----------------+-------------+-------------+--------------+
| submit_time | form_name | field_name | field_value |
+-----------------+-------------+-------------+--------------+
| 1323463601.0947 | Online Form | firstname | Paulo |
| 1323463601.0947 | Online Form | lastname | Hill |
+-----------------+-------------+-------------+--------------+
How can I construct a query that will get a single result (if possible) by searching for Paulo Hill?
Also, the submit_time column should have the same value for both rows--that will be the one column value that is unique in the table.
You could use a self-join:
SELECT t1.submit_time, t1.field_value, t2.field_value
FROM your_table t1
INNER JOIN your_table t2 ON t2.submit_time = t1.submit_time
WHERE t1.field_name = 'firstname'
AND t1.field_value = 'Paulo'
AND t2.field_name = 'lastname'
AND t2.field_value = 'Hill'
Supposing 'paulo hill' is a single search query:
SELECT t1.*,
t2.field_value
FROM tbl t1
INNER JOIN tbl t2 ON t1.submit_time = t2.submit_time
AND t2.field_name = 'lastname'
WHERE t1.field_name = 'firstname'
AND t1.field_value || ' ' || t2.field_value = 'paulo hill'
Note: this solution is sensitive to amount of spaces between first name and last name in search query
try this:
SELECT * FROM (
SELECT submit_time, group_concat(field_value SEPARATOR ' ') AS fullname
FROM TABLE_NAME
GROUP BY `submit_time`
) AS innertable
WHERE fullname='Paulo Hill'
One alternative is to use GROUP_CONCAT if you know the order:
SELECT GROUP_CONCAT(field_value SEPARATOR ' ')
FROM tab
GROUP BY submit_time
HAVING GROUP_CONCAT(field_value ORDER BY field_id ASC) LIKE '%Paulo,Hill%'
I have three tables:
table "package"
-----------------------------------------------------
package_id int(10) primary key, auto-increment
package_name varchar(255)
price decimal(10,2)
table "zones"
------------------------------------------------------
zone_id varchar(32) primary key (ex of data: A1, Z2, E3, etc)
table "package_zones"
------------------------------------------------------
package_id int(10)
zone_id varchar(32)
What I'm trying to do is return all the information in package table PLUS a list of zones for that package. I want the list of zones sorted alphabetically and comma separated.
So the output I'm looking for is something like this:
+------------+---------------+--------+----------------+
| package_id | package_name | price | zone_list |
+------------+---------------+--------+----------------+
| 1 | Red Package | 50.00 | Z1,Z2,Z3 |
| 2 | Blue Package | 75.00 | A2,D4,Z1,Z2 |
| 3 | Green Package | 100.00 | B4,D1,D2,X1,Z1 |
+------------+---------------+--------+----------------+
I know I could do something in PHP with the presentation layer to get the desired result. The problem is, I would like to be able to sort zone_list ASC or DESC or even use WHERE zone_list LIKE and so on. In order to do that, I need this done in MySQL.
I have NO idea how to even begin to tackle this. I tried using a subquery, but it kept complaining about multiple rows. I tried to concat the multiple rows into a single string, but evidently MySQL doesn't like this.
Thanks in advance.
UPDATE!
Here is the solution for those who are interested:
SELECT
`package`.*,
GROUP_CONCAT(`zones`.`zone` ORDER BY `zones`.`zone` ASC SEPARATOR ',' ) as `zone_list`
FROM
`package`,
`package_zones`
LEFT JOIN
(`zones`,`ao_package_zones`) ON (`zones`.`zone_id` = `package_zones`.`zone_id` AND `package_zones`.`package_id` = `package`.`package_id`)
GROUP BY
`ao_package`.`package_id`
by using the GROUP_CONCAT() function and a GROUP BY call. here's an example query
SELECT
p.package_id,
p.package_name,
p.price,
GROUP_CONCAT(pz.zone_id SEPARATOR ',') as zone_list
FROM
package p
LEFT JOIN package_zone pz ON p.package_id = pz.package_id
GROUP BY
p.package_id
you should still be able to order by zone_id s (or zone_list), and instead of using LIKE, you can use WHERE zp.zone_id = 'Z1' or something similar.
I have a customer who requested me to generate a query to use in a prestashop database to get the last year records from ps_orders, ps_customer tables; and one of those column was "The list of product ids in the order" from the ps_order_detail table. So, my query result was:
SELECT
o.id_order, o.reference,
(
SELECT
GROUP_CONCAT(od.product_id SEPARATOR ', ') AS products
FROM ps_order_detail od
WHERE od.id_order = o.id_order
GROUP BY od.id_order
) AS product_ids,
CONCAT(c.firstname, ' ', c.lastname) AS customer, o.current_state, o.payment, o.total_discounts,
o.total_discounts_tax_incl, o.total_discounts_tax_excl, o.total_paid, o.total_paid_tax_incl,
o.total_paid_tax_excl, o.total_products, o.total_products_wt, o.total_shipping, o.total_shipping_tax_incl,
o.total_shipping_tax_excl, o.carrier_tax_rate, o.total_wrapping, o.total_wrapping_tax_incl,
o.total_wrapping_tax_excl, o.invoice_number, o.delivery_number, o.valid
FROM ps_orders o
INNER JOIN ps_customer c ON c.id_customer = o.id_customer
WHERE
o.date_add <= NOW() AND o.date_add >= DATE_ADD(NOW(), INTERVAL - 12 MONTH);
Result: