mysql select update - mysql

Got this:
Table a
ID RelatedBs
1 NULL
2 NULL
Table b
AID ID
1 1
1 2
1 3
2 4
2 5
2 6
Need Table a to have a comma separated list as given in table b. And then table b will become obsolete:
Table a
ID RelatedBs
1 1,2,3
2 4,5,6
This does not rund through all records, but just ad one 'b' to 'table a'
UPDATE a, b
SET relatedbs = CONCAT(relatedbs,',',b.id)
WHERE a.id = b.aid
UPDATE: Thanks, 3 correct answers (marked oldest as answer)! GROUP_CONCAT is the one to use. No need to insert commas between the ids using relatedids = CONCAT(relatedids,',',next_id) that is done automatic by GROUP_CONCAT.

You'll have to use the mysql group_concat function in order to achieve this: http://dev.mysql.com/doc/refman/5.1/en/group-by-functions.html#function_group-concat

Look into GROUP_CONCAT(expr)
mysql> SELECT student_name,
-> GROUP_CONCAT(DISTINCT test_score
-> ORDER BY test_score DESC SEPARATOR " ")
-> FROM student
-> GROUP BY student_name;

You can't do that in standard SQL. You could write a stored procedure to do that. I had a similar problem, but I was using PostgreSQL so I was able to resolve it by writing a custom aggregate function so that you can do queries like
select aid, concat(id)
from b group by
aid
Update: MySQL has a group_concat aggregate function so you can do something like
SELECT id,GROUP_CONCAT(client_id) FROM services WHERE id = 3 GROUP BY id
as outlined here.

Related

How to treat missing id 's value as 0 and order by it?

When I use in keyword in sql, there may be some id is missing , but I want treat them like they exist and other columns are null or 0.
For example, suppose I have a table with two columns and some rows:
[id,value1]
1      1
2      4
3      3
5      5
I may write sql like this:
select * from table where id in (1,4,5) order by value1 limit 0,2 ;
When this sql is executed, the return result is [(1,1),(5,5)].
But what I want is [(4,0),(1,1)], because I want to treat the missing id 4 like it exists in the table.
So the question is : Is there some elegant way to achieve it using sql instead of select all rows and sort them in memory.
Use a left join:
select *
from (select 1 as id union all
select 4 union all
select 5
) i left join
table t
using (id)
order by t.value1
limit 0, 2 ;
Note that you are ordering by a value in the existing table, so this depends on the fact that NULL is ordered before other values.

What will be Mysql query for group by and order by dictionary style?

Trying to fetch data and print as like dictionary.
Table:
blog_tags
id name
1 atag1
2 atag2
3 dtag1
4 etag1
5 etag2
6 ctag1
7 ctag2
8 ctag3
9 ztag1
I want the data output as:
A
atag1
atag2
C
ctag1
ctag2
D
dtag1
E
etag1
etag2
Z
ztag1
Started with this:
select name from blog_tags order by name;
what will be mysql query for this?
Try something like this
select name
from (
select distinct upper(substring(name, 1, 1)) as name
from blog_tags
union all
select name
from blog_tags
)
order by name
Edit
If you want to get raw data for application level manipulation, I would suggest querying the db this way
select upper(substring(name, 1, 1)) as key,
name
from blog_tags
order by 1, 2
You can use the bellow query to achieve this as given below
select substr(name,1,1),group_conact(name) from blog_tags group by substr(name,1,1);
This query will group the name's by first character and will group concat the name's as comma separated. You can convert the result from your programming language to array
The output will be like given below
substr(name,1,1) group_conact(name)
A atag1,atag2
C ctag1,ctag2

stuck; SQL case statement with aggregate function

I am stuck on a problem and I am hoping that you guys can help.
I am running mySQL with XAMPP and PHP My Admin (PMA)
I have two tables:
Table A
A |B
1000000001 |100000001
1000000001 |100000002
1000000001 |100000003
1000000002 |100000004
1000000002 |100000005
1000000003 |100000006
Table B
C |D
1000000001|100000000000001
1000000002|100000000000002
1000000003|100000000000003
1000000004|100000000000004
1000000005|100000000000005
1000000006|100000000000006
I have joined the two tables to represent the following:
A |B/C |D
100000001|1000000001|100000000000001
100000001|1000000002|100000000000002
100000001|1000000003|100000000000003
100000002|1000000004|100000000000004
100000002|1000000005|100000000000005
100000003|1000000006|100000000000006
Notice the pattern that occurs in the first three data points.
Essentially I need help understanding how to write a case script That would return a unique A value and the Count of the D value per A value
The Return would be:
A |D_COUNT
100000001|3
100000001|2
100000003|1
Thank you!
SELECT A,
COUNT(DISTINCT D) AS count_d
FROM table_c
GROUP BY A;
The tables you give seems to be a bit of a mistake,the length of TableA.B is 9 and TableB.C is 10 ,ignore this,you may write your query string like this:
select A,count(A) as D_COUNT
from t_a,t_b
where t_a.b=t_b.c
group by t_a.A;
TableA ==> t_a
TableB ==> t_b
Try this query:
select A,count(A) as D_Count from tablename group by A

How to delete a row where there are only one of the kind in MySql?

I have following data in MySQL table named info:
chapter | section
3 | 0
3 | 1
3 | 2
3 | 3
4 | 0
5 | 0
I would like to delete a row for chapter = n, but only when there is no section>0 for same chapter. So chapter 3 can't be deleted while chapter 4 and 5 can. I know the following doesn't work:
DELETE info WHERE chapter = 3 AND NOT EXISTS (SELECT * FROM info WHERE chapter = 3 AND section>0);
The same table is used twice in the statement. So what is the easiest way to achieve my goal?
You've got the idea right. Here is the syntax:
DELETE
FROM mytable
WHERE chapter NOT IN (
SELECT * FROM (
select tt.chapter
from mytable tt
where tt.section <> 0
group by tt.chapter
) tmp
)
The nested select is a workaround a bug in MySQL.
Demo.
You can run a sub query to return the rows that have sections of more then one and then delete the rows returned from the sub query.
DELETE FROM table1 WHERE table1.chapter Not IN (select chapter from
(SELECT table1.chapter FROM table1 WHERE Table1.section >=1 ) Results);
Example Fiddle based on your question
You could also supply the chapter as well in the sub query where clause if you only want to delete a specfic chapter. If it does not meet the where clause then no records will be deleted.
This should do it.
DELETE FROM Table t
WHERE NOT EXISTS(
SELECT 1
FROM Table t2
Where t2.chapter = t.chapter
And t2.section > 0
)
In my experience Exists generally performs better than In. If you are storing a large amount of records you should take this into consideration.

Oracle/MYSQL: Sort records from a select query on a column that contains alphanumeric values

I know that this question has been asked in various forms but my requirement happens to be a bit different.
Suppose I have a table that contains data as follows:
ID NAME VALUE
-----------------------------
1 ABC-2-2 X
2 PQRS-1-3 Y
3 ABC-3-2 Z
4 PQRS-1-4 A
5 PQRS-3-4 B
6 MNO-2-1 C
7 AAA-1 D
8 BBB-2 E
9 CCC-3 F
Now, the output that I'm expecting should look something like this:
ID NAME VALUE
-----------------------------
7 AAA-1 D
2 PQRS-1-3 Y
4 PQRS-1-4 A
8 BBB-2 E
6 MNO-2-1 C
1 ABC-2-2 X
9 CCC-3 F
3 ABC-3-2 Z
5 PQRS-3-4 B
Note that this is not a direct alpha-numeric sort. Instead, the value before the first "-" is ignored and the fields are sorted on what is after the first "-" in the name.
I'm not very familiar with PL/SQL and any kind of help on this would be appreciated.
Thanks.
PS: Note that this should work on both Oracle and MySQL.
For your example this would suffice (Oracle syntax):
ORDER BY SUBSTR(name,4)
If the number of characters before the first hyphen can vary, you can do this (again Oracle syntax):
ORDER BY SUBSTR(name,INSTR(name,'-')+1)
However that won't work if you have codes like:
AAA-10-1
AAA-8-1
AAA-9-1
and expect AAA-10-1 to appear after AAA-9-1. Then you will need to parse it further:
ORDER BY LPAD(SUBSTR(name,INSTR(name,'-')+1, INSTR(name,'-',1,2)-INSTR(name,'-')-1),10,'0'),
LPAD(SUBSTR(name,INSTR(name,'-',1,2)+1),10,'0')
(NB I have used LPAD(x,10,'0') to turn a value like '1' into '0000000001' and so on, rather than use TO_NUMBER since this could fail if there are any non-numerics in your data.)
Example:
with data as
(
select 'AAA-1' name from dual
union all
select 'PQR-1-4' name from dual
union all
select 'PQR-1-3' name from dual
union all
select 'AAA-10-10' name from dual
union all
select 'AAA-10-1' name from dual
union all
select 'AAA-9-10' name from dual
union all
select 'AAA-9-1' name from dual
)
select *
from data
ORDER BY LPAD(SUBSTR(name,INSTR(name,'-')+1, INSTR(name,'-',1,2)-INSTR(name,'-')-1),10,'0'),
LPAD(SUBSTR(name,INSTR(name,'-',1,2)+1),10,'0');
Output:
NAME
---------
PQR-1-3
PQR-1-4
AAA-9-1
AAA-9-10
AAA-10-1
AAA-10-10
AAA-1
And if AAA-1 should come first:
ORDER BY LPAD(SUBSTR(name,INSTR(name,'-')+1, INSTR(name||'-','-',1,2)-INSTR(name,'-')-1),10,'0'),
LPAD(SUBSTR(name,INSTR(name||'-','-',1,2)+1),10,'0') nulls first
Not sure about mysql syntax, but you can do this in oracle:
select * from <your_table>
order by substr(name, 5)
in mssql the syntax of finding your problem is :
select * from mytable order by substring(name,PATINDEX('%-%',name)+1,len(name)-PATINDEX('%-%',name))
SqlFiddle