i want to select a column but with diferent order :
i have 2 table :
table_name:
+------+-----------+
| id | name |
+------+-----------+
| 1 | Sindra |
| 2 | Auli |
| 3 | Brian |
| 4 | Bina |
| 5 | zian |
| 6 | Bri |
| 7 | Andre |
+------+-----------+
table_temp, id_temp_name foreign key of id(table_name) :
+------+--------------+
| id | id_temp_name |
+------+--------------+
| 1 | 1 |
| 2 | 3 |
| 3 | 4 |
| 4 | 2 |
+------+--------------+
with this query :
SELECT *
FROM table_name
WHERE id IN
(SELECT id_temp_name FROM table_temp)
the result is always same look with table_name, i was looking for result that exactly same with id_temp_name order , so the result will be :
+------+-----------+
| id | name |
+------+-----------+
| 1 | Sindra |
| 3 | Brian |
| 4 | Bina |
| 2 | Auli |
+------+-----------+
thanks for any advice, .
You need to rewrite the query to be a JOIN between both tables, then you can set an ordering based on any column involved, even when not in the final result set:
SELECT table_name.id,
table_name.name
FROM table_name
INNER JOIN table_temp ON table_name.id = table_temp.id_temp_name
ORDER BY table_temp.id ;
Use a join instead of a sub-query.
SELECT table_name.id, table_name.name
FROM table_name
INNER JOIN table_temp ON table_name.id = table_temp.id
ORDER BY table_temp.id_temp_name
And... usually best to list the fields explicitly instead of using * to select all.
You should use a simple JOIN to achieve your result.
Your query:
SELECT *
FROM table_name
WHERE id IN
(SELECT id_temp_name FROM table_temp)
actually returns all the rows and columns of the table_name Table. So you won't get the desired id_temp_name results, since it's in a different table. That's why, you should use LEFT JOIN, since your left table is table_name, and your right table is table_temp, and you want to show data from a column of table_temp, which is id_temp_name.
So, what you need to do, is this:
SELECT tn.id, tn.name
FROM table_name AS tn
LEFT JOIN table_temp AS tt
ON tn.id= tt.id_temp_name
GROUP BY tn.id
Related
I have a following table in my project
+----+--------+-----------+-----------+
| id | old_id | op_status | tr_status |
+----+--------+-----------+-----------+
| 1 | | issue | Approved |
| 2 | | issue | Approved |
| 3 | | issue | Approved |
| 4 | 1 | issue | Issued |
| 5 | 3 | issue | Issued |
+----+--------+-----------+-----------+
I want to select records WHERE tr_status='Approved' and NOT IN id in the old_row_id. In this example no need to select id(s) 1 and 3 that are in old_row_id as the following result.
+----+--------+-----------+-----------+
| id | old_id | op_status | tr_status |
+----+--------+-----------+-----------+
| 2 | | issue | Approved |
+----+--------+-----------+-----------+
I used the following query.
SELECT id, old_row_id, op_status, tr_status FROM table WHERE id NOT IN (old_row_id).
But outs the following result.
+----+--------+-----------+-----------+
| id | old_id | op_status | tr_status |
+----+--------+-----------+-----------+
| 1 | | issue | Approved |
| 2 | | issue | Approved |
| 3 | | issue | Approved |
+----+--------+-----------+-----------+
What may be wrong with me ? can anyone help me ?
I would phrase your query using exists logic:
SELECT t1.id, t1.old_id, t1.op_status, t1.tr_status
FROM yourTable t1
WHERE
t1.tr_status = 'Approved' AND
NOT EXISTS (SELECT 1 FROM yourTable t2 WHERE t2.old_id = t1.id);
Demo
Try doing something like this:
SELECT id, old_id, op_status, tr_status
FROM table
WHERE id NOT IN (SELECT DISTINCT old_id FROM table)
AND tr_status = 'Approved'
You will want to left join the table to itself on the old ID, then eliminate the records where there is a match.
For example:
SELECT A.id, A.old_row_id, A.op_status, A.tr_status
FROM table A
LEFT JOIN table B ON A.id = B.old_row_id
WHERE B.id IS NULL
AND A.tr_status = 'Approved';
In they way you've tried to solve it, you're matching the old_id with the value of the row itself. You must derivate the table to create a cartesian product:
SELECT id, old_id, op_status, tr_status
FROM table
WHERE id NOT IN (SELECT IFNULL(old_id, 0) FROM table)
AND tr_status = 'Approved'
Also IFNULL to also include those record in the subquery, otherwise can't be compared with null
I have 2 tables:
clients_db
| clnt_id | clnt_sid | usr_sid | clnt_name |
| 1 | 12345678 | 10001 | Peter |
| 2 | 87654321 | 10001 | Mikey |
aircon_client_db
| ac_id | clnt_sid |
| 1 | 12345678 |
| 2 | 12345678 |
| 3 | 12345678 |
| 4 | 87654321 |
| 5 | 87654321 |
This is query:
select *,count(air.ac_id) as nAC
from clients_db clnt
left join aircon_client_db air on air.clnt_sid=clnt.clnt_sid
where clnt.usr_sid=?
group by clnt.clnt_sid
order by clnt.clnt_name asc
From the code above. I expect the result clnt_id[1]=3 and clnt_id[2]=2. But the result returns 0 for all. Where should I fix?
You just need to select the count(air.ac_id).
Also replace clnt.usr_sid=? with clnt.clnt_id=? if you're going to expect a result like clnt_id[1]=3.
select count(air.ac_id) as nAC
from clients_db clnt
left join aircon_client_db air on air.clnt_sid=clnt.clnt_sid
where clnt.clnt_id=?
group by clnt.clnt_sid
order by clnt.clnt_name asc
Are you missing clnt_name as column in your question?
Don't use * but explicit column name or in this case you could also use clnt.* (you don't need the value for the left joined table but only the count(*)
select clnt.clnt_id, clnt.clnt_sid ,count(air.ac_id) as nAC
from clients_db clnt
left join aircon_client_db air on trim(air.clnt_sid)=trim(clnt.clnt_sid)
AND trim(clnt.user_sid)= '10001'
group by clnt.clnt_sid
order by clnt.clnt_name asc
I'm trying to concatenate data from three related tables according to:
orders orderrow orderrow_op
+----+ +----+----------+ +----+-------------+
| id | | id | id_order | | id | id_orderrow |
+----+ +----+----------+ +----+-------------+
| 1 | | 1 | 1 | | 1 | 1 |
| 2 | | 2 | 1 | | 2 | 1 |
| 3 | | 3 | 2 | | 3 | 2 |
+----+ | 4 | 3 | | 4 | 3 |
+----+----------+ | 5 | 3 |
| 6 | 3 |
+----+-------------+
The result i'm looking for is something like:
orderops (Desired Result)
+----------+-----------------+
| id_order | id_row:id_ops |
+----------+-----------------+
| 1 | 1:(1,2); 2:(3); |
| 2 | 3:(4,5,6) |
| 3 | 4:NULL |
+----------+-----------------+
I.e i want the operations and rows all be displayed on one row related to the order. So far i've tried things like:
SELECT
db.orders.id AS orderid,
db.orderrow.id AS rowids,
GROUP_CONCAT(DISTINCT db.orderrow.id) AS a,
GROUP_CONCAT(db.orderrow.id, ':', db.orderrow_op.id) AS b
FROM
db.orders
LEFT JOIN db.orderrow ON db.orders.id = db.orderrow.id_order
LEFT JOIN db.orderrow_op ON db.orderrow.id = db.orderrow_op.id_orderrow
GROUP BY orderid
Where in column 'a' i get the row ids and in column 'b' i get the operation_ids with corresponding row_id prepended. I'd like to combine the two into a single column such that related values in 'b' will start of with id from 'a' and only show once.
I'm fairly new to MySQL so i don't know if this is even possible or if i'ts a good idea at all? The aim is to structure the data into JSON for delivery via REST application so perhaps it's better to deliver the rows directly to the webserver and handle json parsing over there? I just figured that this approach might be faster.
This is not the nicest query but it's working for your example table setup.
SELECT
o.id AS id_order,
group_concat(sub.ops
SEPARATOR ' ') AS id_row_id_ops
FROM
(SELECT
orderrow.id_order,
IF(isnull(l3.ops), concat(orderrow.id, ':', 'NULL'), concat(orderrow.id, ':', l3.ops)) as ops
FROM
orderrow
LEFT JOIN (SELECT
orderrow_op.id_orderrow,
concat('(', group_concat(orderrow_op.id), '); ') as ops
FROM
orderrow_op
GROUP BY orderrow_op.id_orderrow) l3 ON l3.id_orderrow = orderrow.id) sub
LEFT JOIN
orders o ON o.id = sub.id_order
GROUP BY o.id;
One of the things to mind is the LEFT JOIN and that you need to cast a "null" value to a "null" text (otherwise your element 4 will vanish).
The output:
I am trying to join two tables and only select the dealers that did not have their promo code used on any order.
How can I do this?
I'm trying this below, but it's not working right. In the example I want to get just Bob, since his promo_code hasn't been used in any orders.
SELECT d.`name`
FROM z_dealer d
LEFT OUTER JOIN z_order o ON (d.promo_code = o.promo_code)
AND o.promo_code IS NULL
Here are my tables...
mysql> select * from z_dealer;
+----+------+------------+
| id | name | promo_code |
+----+------+------------+
| 1 | John | holiday |
| 2 | Suzy | special |
| 3 | Bob | laborday |
+----+------+------------+
mysql> Select * from z_order;
+----+-------+------------+
| id | total | promo_code |
+----+-------+------------+
| 1 | 10 | holiday |
| 2 | 20 | special |
| 3 | 15 | holiday |
| 4 | 45 | special |
+----+-------+------------+
SELECT d.`name` FROM z_dealer d LEFT JOIN z_order o ON (d.promo_code = o.promo_code) WHERE o.promo_code IS NULL
Have you tried INNER JOIN? or You can try IN like this :
SELECT d.name
FROM z_dealer d
WHERE d.promo_code not in( SELECT promo_code FROM z_order)
I'm not entirely sure why it's not working in your example code. I've created the same tables locally and when I run the script you provided I get the single 'Bob' answer.
SELECT d.name
FROM z_dealer d
LEFT OUTER JOIN z_order o ON (d.promo_code = o.promo_code)
AND o.promo_code IS NULL
What results are you seeing exactly?
I have some MySQL results like this:
---------------------------
| name | something_random |
---------------------------
| john | ekjalsdjalfjkldd |
| alex | akjsldfjaekallee |
| alex | jkjlkjslakjfjflj |
| alex | kajslejajejjaddd |
| bob | ekakdie33kkd93ld |
| bob | 33kd993kakakl3ll |
| paul | 3k309dki595k3lkd |
| paul | 3k399kkfkg93lk3l |
etc...
This goes on for 1000's of rows of results. I need to limit the number of results to the first 50 unique names. I think there is a simple solution to this but I'm not sure.
I've tried using derived tables and variables but can't quite get there. If I could figure out how to increment a variable once every time a name is different I think I could say WHERE variable <= 50.
UPDATED
I've tried the Inner Join approach(es) suggested below. The problem is this:
The subselect SELECT DISTINCT name FROM testTable LIMIT 50 grabs the first 50 distinct names. Perhaps I wasn't clear enough in my original post, but this limits my query too much. In my query, not every name in the table is returned in the result. Let me modify my original example:
----------------------------------
| id | name | something_random |
----------------------------------
| 1 | john | ekjalsdjalfjkldd |
| 4 | alex | akjsldfjaekallee |
| 4 | alex | jkjlkjslakjfjflj |
| 4 | alex | kajslejajejjaddd |
| 6 | bob | ekakdie33kkd93ld |
| 6 | bob | 33kd993kakakl3ll |
| 12 | paul | 3k309dki595k3lkd |
| 12 | paul | 3k399kkfkg93lk3l |
etc...
So I added in some id numbers here. These ID numbers pertain to the people's names in the tables. So you can see in the results, not every single person/name in the table is necessarily in the result (due to some WHERE condition). So the 50th distinct name in the list will always have an ID number higher than 49. The 50th person could be id 79, 234, 4954 etc...
So back to the problem. The subselect SELECT DISTINCT name FROM testTable LIMIT 50 selects the first 50 names in the table. That means that my search results will be limited to names that have ID <=50, which is too constricting. If there are certain names that don't show up in the query (due to some WHERE condition), then they are still counted as one of the 50 distinct names. So you end up with too few results.
UPDATE 2
To #trapper: This is a basic simplification of what my query looks like:
SELECT
t1.id,
t1.name,
t2.details
FROM t1
LEFT JOIN t2 ON t1.id = t2.some_id
INNER JOIN
(SELECT DISTINCT name FROM t1 ORDER BY id LIMIT 0,50) s ON s.name = t1.name
WHERE
SOME CONDITIONS
ORDER BY
t1.id,
t1.name
And my results look like this:
----------------------------------
| id | name | details |
----------------------------------
| 1 | john | ekjalsdjalfjkldd |
| 3 | alex | akjsldfjaekallee |
| 3 | alex | jkjlkjslakjfjflj |
| 4 | alex | kajslejajejjaddd |
| 6 | bob | ekakdie33kkd93ld |
| 6 | bob | 33kd993kakakl3ll |
| 12 | paul | 3k309dki595k3lkd |
| 12 | paul | 3k399kkfkg93lk3l |
...
| 37 | bill | kajslejajejjaddd |
| 37 | bill | ekakdie33kkd93ld |
| 41 | matt | 33kd993kakakl3ll |
| 50 | jake | 3k309dki595k3lkd |
| 50 | jake | 3k399kkfkg93lk3l |
----------------------------------
The results stop at id=50. There are NOT 50 distinct names in the list. There are only roughly 23 distinct names.
My MySql syntax may be rusty, but the idea is to use a query to select the top 50 distinct names, then do a self-join on name and select the name and other information from the join.
select a.name, b.something_random
from Table b
inner join (select distinct name from Table order by RAND() limit 0,50) a
on a.name = b.name
SELECT DISTINCT name FROM table LIMIT 0,50
Edited: Ahh yes I misread question first time, this should do the trick though :)
SELECT a.name, b.something_random
FROM `table` b
INNER JOIN (SELECT DISTINCT name FROM `table` ORDER BY RAND() LIMIT 0,50) a
ON a.name = b.name ORDER BY a.name
How this work is the (SELECT DISTINCT name FROMtableORDER BY RAND() LIMIT 0,50) part is what pulls out the names to include in the join. So here I am taking 50 unique names at random, but you can change this to any other selection criteria if you want.
Then you join those results back into your table. This links each of those 50 selected names back to all of the rows with a matching name for your final results. Finally ORDER BY a.name just to be sure all the rows for each name end up grouped together.
This should do it:
SELECT tA.*
FROM
testTable tA
INNER JOIN
(SELECT distinct name FROM testTable LIMIT 50) tB ON tA.name = tB.name
;