SQL order by and then replace - mysql

How do you run an "order by" and then "replace" string, but keep the order? Context - I need the string "column_name" to be in the first line, hence using "zzz_column_name" to force it in the order by. And then I need to use replace to change it from "zzz_column_naem" to "column_name".
SELECT replace(column_name, 'zzz_', '')
FROM (
SELECT *
FROM (
SELECT 'zzz_column_name' AS column_name
UNION
SELECT column_name
FROM table
) s
ORDER BY column_name DESC
) a
After the replace in the first line, I'd lose the order achieved by order by.

Just order by the unmodified column. You don't even need a subquery:
SELECT replace(column_name, 'string', '') AS column_name_replaced
FROM (
SELECT 'zzz_column_name' AS column_name
UNION ALL
SELECT column_name FROM table
) s
ORDER BY column_name DESC
Note: UNION ALL is more efficient than UNION - use it unless you have good reasons not to
I am wondering if you are actually trying to put first the row that has the fixed value; in that case, we can simplify the whole thing with just a conditional sort. Assuming a table like mytable(col), we can add a header row with value 'my_header' like so:
SELECT 'my_header' AS col, 1 AS is_header
UNION ALL
SELECT col, 0 FROM mytable
ORDER BY is_header DESC, col
This puts the header row first, followed by all values in order.
If you mind the additional column, we can remove it with a subquery:
SELECT col
FROM (
SELECT 'my_header' AS col, 1 AS is_header
UNION ALL
SELECT col, 0 FROM mytable
) t
ORDER BY is_header DESC, col

You don't need the outer SELECT and you can sort by the original column name
SELECT replace(column_name, 'string', '')
FROM (
SELECT 'zzz_column_name' AS column_name
UNION
SELECT column_name
FROM table
) s
ORDER BY column_name DESC

Related

Can I concatenate multiple MySQL Column into One Column?

Good day i would like to ask if this is possible in MySQL
SELECT id,label,name,age,sex FROM table LIMIT 3
Output
[row1] id,label,name,age,sex
[row2] id,label,name,age,sex
[row3] id,label,name,age,sex
My Output Needed
[row1] id
[row2] label
[row3] name
[row4] age
[row5] sex
[row6] id
[row7] label
[row8] name
[row9] age
[row10] sex
[row11] id
[row12] label
[row13] name
[row14] age
[row15] sex
You can do something like this:
SELECT * FROM
((SELECT id AS id1, 1 AS rownum, 'id' AS colname, id AS Data_value FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 2, 'label', label FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 3, 'name', name FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 4, 'age', age FROM mytable LIMIT 3)
UNION ALL
(SELECT id, 5, 'sex', sex FROM mytable LIMIT 3)) A
ORDER BY id1, rownum
Here's a fiddle: https://www.db-fiddle.com/f/dvg6x1vBg6H5bDNp9VZxQa/4
I've added 3 additional column id AS id1, rownum and colname. The first two additional column is used for ORDER BY at the outer query. If you don't want to see the additional column, you can just type SELECT Data_value FROM ... at the outer query.
You can use group_concat() to aggregate rows by string concatenation. For the LIMIT to work you then need to use a derived table. But you should be careful with a LIMIT without an ORDER BY. As the order of a query result can be random unless an explicit ORDER BY is issued, you may get different results each time you run the query.
SELECT group_concat(id,
'\n',
label,
'\n',
name,
'\n',
age,
'\n',
sex
SEPARATOR '\n')
FROM (SELECT id,
label,
name,
age,
sex
FROM elbat
LIMIT 3) x;
If you just want to concatenate the columns but keep the rows just use concat().
SELECT concat(id,
'\n',
label,
'\n',
name,
'\n',
age,
'\n',
sex)
FROM elbat
LIMIT 3;
yes,you can use union all like below :
SELECT id FROM table LIMIT 3
union all
SELECT label FROM table LIMIT 3
union all
SELECT name FROM table LIMIT 3
union all
SELECT age FROM table LIMIT 3
union all
SELECT sex FROM table LIMIT 3
That what you looking is to Unpivot data. For more info about pivot and unpivot you can check here.
http://archive.oreilly.com/oreillyschool/courses/dba1/dba110.html
Unfortunately there is no easy way to unpivot in mysql.
The below script will work for MySQL 8.0
set #rowNum :=0;
set #string :=(
select group_concat(id,',',label,',',name,',',age,',',sex separator ',')
from (
select id, label, name, age, sex from mytable limit 3
) x
);
with recursive
R1 as ( select #string as items),
R2 as ( select 1 as n
union
select n + 1 from R2, R1
where n <= length(items) - length(replace(items, ',', '')))
select distinct #rowNum := #rowNum+1 as rowNum, substring_index(substring_index(items, ',', n), ',', -1) output from R2, R1;

How to query all tables in a database

I'm writing MySQL to get all unique IDs from all tables in a database.
The database has tables like record_20181201, record_20181202, ...
The tables are automatically generated based on date (all tables have the same schema, and one column name is visitorId).
The SQL query I made is like,
SELECT UNIQUE(visitorId) FROM databaseName.record_20181201;
I can only query one table at a time using this..
Is there a way to query all tables in the database and select all unique visitorIds there?
SELECT DISTINCT VisitorID FROM DBName.Table1
UNION
SELECT DISTINCT VisitorID FROM DBName.Table2
UNION
SELECT DISTINCT VisitorID FROM DBName.Table3
Try this!!!!!!Hope this helps..
You could generate a query string with UNION's from the INFORMATION_SCHEMA.
Then run that query, or put it in a view.
A UNION will return a unique combined result of the unioned queries.
While a UNION ALL would just stick the results together.
SELECT GROUP_CONCAT(Qry ORDER BY TblSchema, TblName SEPARATOR ' UNION ')
FROM
(
SELECT
TABLE_SCHEMA as TblSchema,
TABLE_NAME as TblName,
CONCAT('select visitorId from ',TABLE_SCHEMA,'.',TABLE_NAME,'\r\n') as Qry
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME LIKE 'record_201812%'
AND COLUMN_NAME = 'visitorId'
) Q;
Run below query you will get a single query that will give unique visitorId from all table.
SELECT
CONCAT('SELECT DISTINCT visitorId FROM (',
REPLACE(query_string, ',', ' UNION '),
') union_table') AS final_query
FROM
(SELECT
CONCAT(GROUP_CONCAT('SELECT visitorId FROM ', table_name)) AS query_string
FROM
information_schema.tables
WHERE
table_name LIKE 'record_%') table_a;
you will get below query that will fetch unique visitorId from all tables.
SELECT DISTINCT
visitorId
FROM
(
SELECT visitorId FROM record_20181201
UNION
SELECT visitorId FROM record_20181202
UNION
SELECT visitorId FROM record_20181203
) union_table

How to replace a null value with previous non-null value?

I want to replace a null value with previous non-null value using MySQL.
I tried this:
SELECT
`Date_Column`
,CASE
WHEN `Value_Column` is null
THEN (
SELECT
`Value_Column`
FROM
table_name t2
WHERE
`Date_Column` = (
SELECT
MAX(`Date_Column`)
FROM
table_name t3
WHERE
`Date_Column` < t1.`Date_Column`
AND `Value_Column` > 0
)
)
ELSE `Value_Column`
END AS `Value_Column`
FROM
table_name t1
This works but takes really long for big datasets.
I tried this for a subset of data and it worked.
Is there an easier/more efficient way to achieve the same?
Thanks.
Based on your query, your first check should be that your take is correctly indexed by the date column (and the value column as a covering index). If it is, then you could use the following slightly simplified query.
Note, this replaces NULL as per your description, where yours replaced 0 contrary to your description, you should be clear as to Exactly which behaviour you want.
SELECT
date_column,
COALESCE(
value_column,
(
SELECT lookup.value_column
FROM table_name AS lookup
WHERE lookup.date_column < table_name.date_column
AND lookup.value_column IS NOT NULL
AND table_name.value_column IS NULL
ORDER BY lookup.date_column DESC
LIMIT 1
)
)
FROM
table_name
(on my phone, so please forgive typos)
You can simplify the query to:
SELECT t1.Date_Column
(CASE WHEN t1.Value_Column = 0
THEN (SELECT t2.Value_Column
FROM table_name t2
WHERE t2.Date_Column < t1.Date_Column AND t2.Value_Column > 0
ORDER BY t2.Date_Column DESC
LIMIT 1
)
ELSE t2.Value_Column
END) AS Value_Column
FROM table_name t1;
This is an improvement on your query because it removes the second nested subquery. But it will still be slow. An index on table_name(Date_Column, Value_Column) might help.

store multiple query results at a time (mysql)

I want to store the results of query
SELECT column_name from table_name limit 2
into variables, says, #w1 , #w2
What are the correct syntax?
I tried
"Set #w1, #w2 = (SELECT column_name from table_name limit ); "
and similar ones but it hasn't work.
Thank.
You can try the following:
SELECT * FROM
(SELECT #a := (SELECT column_name FROM table_name ORDER BY value LIMIT 1) as a) a,
(SELECT #b := (SELECT column_name FROM table_name ORDER BY value LIMIT 1 OFFSET 1) as b) b
Please note that limit won't make much sense if you do not use ORDER BY.

How to insert max 3 results in different columns?

I would like to insert max 3 results of a column into 3 different columns.
SELECT
t.name,
m.top_marks
FROM
table_name t,
(SELECT
marks
FROM table_name
WHERE rownum <=3
ORDER BY marks DESC) m
GROUP BY column_name DESC;
This can help me to get top 3 marks right? but what if i want to store top 3 results in 3 new columns? Marks1, marks2, marks3?
I can't say I really understand what you are going for... But it sounds like you might want the LIMIT operator. See this:
SQL - Select first 10 rows only?
So maybe something like this?
SELECT
t.name,
m.top_marks
FROM
table_name t,
(SELECT
marks
FROM table_name
ORDER BY marks DESC
LIMIT 3) m
GROUP BY column_name DESC;
You can do this with the group_concat()/substring_index() method:
SELECT t.name,
substring_index(m.marks, ',', 1) as Mark1,
substring_index(substring_index(m.marks, ',', 2), ',', -1) as Mark2,
substring_index(substring_index(m.marks, ',', 3), ',', -1) as Mark3
m.top_marks
FROM table_name t cross join
(SELECT group_concat(marks order by marks desc) as marks
FROM table_name
) m
GROUP BY column_name DESC;
If it is sufficient to have them in one column with commas separating the values:
SELECT t.name, substring_index(m.marks, ',', 3) as Marks3
FROM table_name t cross join
(SELECT group_concat(marks order by marks desc) as marks
FROM table_name
) m
GROUP BY column_name DESC;