I have a MySQL query that always needs to compare 4 values, I need to add that values with rows using UNION ALL, but this code looks very large and I want to simplify it.
The code is the following:
SELECT
trimestre,
IF ((meta = 0) OR (meta is null) or not(meta REGEXP '[0-9]+'), :meta, meta) as valor
FROM
(
SELECT
trimestre,
valor AS meta
FROM
view_valores_indicadores
WHERE
anio = :anio
AND codigo_indicador = :codigo_indicador
AND alias_campo = 'meta'
UNION ALL
SELECT
1,
:meta
UNION ALL
SELECT
2,
:meta
UNION ALL
SELECT
3,
:meta
UNION ALL
SELECT
4,
:meta
ORDER BY
trimestre ASC
) AS T
GROUP BY
TRIMESTRE
I want to know if is possible to simplify that multiple UNION ALL's like
UNION ALL SELECT (row1, row1, row3...)
Related
Currently trying to transform some text in MySQL. Could use some help since I'm running into some problems trying to use some aggregate functions.
I've got a column stay that's got values that I can use for the most part, but I've got instances where the output is More than 100 Days. I'm currently trying to get rid of everything but the 100. I've tried using TRIM functions, but I haven't had any luck. I can only get rid of either More than or Days but not both. I also know I can't use TRIM(BOTH) since the text before and after 100 is different.
Any ideas?
This might come across pretty unorthodox but how about making use of datetime functions:
SELECT t.stay,
-- actual logic to fetch the digits
(DATEDIFF(
STR_TO_DATE(CONCAT((#var_some_year := 1000), t.stay),
-- the pattern
'%YMore than %j Days'
),
MAKEDATE(#var_some_year, 1)) + 1
) AS Digits
FROM
(
-- mimicinf your table
SELECT CONCAT('More than ', (#var:= #var + 1), ' Days') AS stay
FROM (SELECT #var:= 0) twofold0
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold1
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold2
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold3
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold4
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold5
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold6
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold7
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold8
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold9
JOIN (SELECT NULL UNION ALL SELECT NULL) twofold10
) t
;
Seems to work for up to 4 digit patterns.
In postgres, I use this kind of sql often.
with list (id, name) as (
values
(1004007, 'aaa'),
(1002147, 'bbb'),
(1004493, 'ccc'),
(1007978, 'ddd'),
(1005218, 'eee'),
(1005507, 'fff')
)
select * from list;
Dose Mysql support that kind of sql ?
You can use select:
with list (id, name) as (
select 1004007, 'aaa' union all
select 1002147, 'bbb' union all
select 1004493, 'ccc' union all
select 1007978, 'ddd' union all
select 1005218, 'eee' union all
select 1005507, 'fff'
)
select l.*
from list l;
Here is a db<>fiddle. Note: This also works in Postgres.
Pre 8.0 versions of MySQL do not support with. You can create a derived table:
select list.*
from (select 1004007, 'aaa' union all
select 1002147, 'bbb' union all
select 1004493, 'ccc' union all
select 1007978, 'ddd' union all
select 1005218, 'eee' union all
select 1005507, 'fff'
) list;
This can then be used just a like a table reference.
Later 8.0 in mysql , we can use it like bellow
with
list (a, b, c) as (VALUES
ROW('1',-2,3),
ROW('5',7,9),
ROW('4',6,8)
)
select * from list;
Is there a way to do the following query? It would save me having to go out of SQL to do post-processing of the query:
SELECT date, RANDOM('CA', 'DE', 'AZ') FROM table LIMIT 3
And the result would be something like:
2014-01-01,"CA"
2014-01-02,"CA"
2014-01-03,"DE"
Is there a way to do the RANDOM operation in SQL?
Get your set of values to table/subquery with UNION ALL, sort by RAND() and return 1 value:
SqlFiddleDemo
SELECT id,
(SELECT 'CA' AS 'col'
UNION ALL
SELECT 'DE'
UNION ALL
SELECT'CZ'
ORDER BY RAND() LIMIT 1) AS Random
FROM tab
LIMIT 3
Or use:
SqlFiddleDemo_2
SELECT id,
ELT(FIELD(CEILING(RAND()*3), 1, 2, 3),'CA','CZ', 'DE') AS Rand
FROM tab
LIMIT 3
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('CA,DE,AZ',',',CEILING(RAND()*3)),',',-1);
or something like that
One way is this if you want to select the random string
select any_column_name,ELT(FLOOR(RAND()*8)+1,'US', 'CA', 'FR', 'DE' , 'UK' , 'IR' ,
'RU' , 'GR') from table_name;
Let me know if that is what you want.
People
here is my little problem.
I have three table:
a_names_1
b_names_2
c_names_3
they are same by structure. all of them has two item: name and used
Is there any QUERY to run to get and count all the 'name' that has 'used'=1 from all those three tables together.
I've tried this one, but didn't work:
(SELECT COUNT(*) 'name' from a_names_1) UNION
(SELECT COUNT(*) 'name' from a_names_2) UNION
(SELECT COUNT(*) 'name' from a_names_3) WHERE `used`=1
I'm using PHPMyAdmin for MySQL.
Any Help would be appreciated.. thanks in advance
This query outputs count of distinct names from all tables with used=1
select count(distinct name)
from
(
select name,used from a_names_1 where used=1
union all
select name,used from a_names_2 where used=1
union all
select name,used from a_names_3 where used=1
) t
If you need to SUM all USED for each NAME from all tables and output only with SUM of used=1 then:
select count(*) from
(
select name, SUM(used)
from
(
select name,used from a_names_1
union all
select name,used from a_names_2
union all
select name,used from a_names_3
) t
GROUP BY name
HAVING SUM(used)=1
) t1
select count(*) as name
from
(
select name, used from a_names_1
union
select name, used from a_names_2
union
select name, used from a_names_3) t
where t.used = 1
Probably this is slow, because you lose the index optimizations. What I would do is do the three queries, something like
SELECT SUM('name') AS name_sum
FROM ((SELECT COUNT(*) 'name' from a_names_1 WHERE `used`=1)
UNION (SELECT COUNT(*) 'name' from a_names_2 WHERE `used`=1));
If this doesn't work, it is probably a problem with the usage of name
Maybe you wanted this way:
select count(*) as cnt
from
(
select name from a_names_1 t1 where t1.used = 1
union
select name from a_names_2 t2 where t2.used = 1
union
select name from a_names_3 t3 where t3.used = 1
) t
The straight forward solution;
SELECT SUM(used) FROM (
SELECT used FROM a_names_1 WHERE used=1
UNION ALL
SELECT used FROM a_names_2 WHERE used=1
UNION ALL
SELECT used FROM a_names_3 WHERE used=1
) a
SQLfiddle for testing
An alternative if you have an index on used (and the only values of used are 0 or 1) is to just do the counting using the index;
SELECT SUM(used) total FROM (
SELECT SUM(used) used FROM a_names_1
UNION ALL
SELECT SUM(used) FROM a_names_2
UNION ALL
SELECT SUM(used) FROM a_names_3
) a
SQLfiddle for this example.
If you look at the query plan of the latter query, you can see it uses the indexes effectively.
I have this query:
SELECT COUNT(*) AS invoice_count, IFNULL(SUM(qa_invoices.invoice_total), 0)
AS invoice_total, IFNULL(SUM(qa_invoices.invoice_discount) ,0) AS invoice_discount
FROM qa_invoices
WHERE (DATE(qa_invoices.invoice_date) BETWEEN '12/06/25' AND '12/06/25')
AND qa_invoices.status_code IN (5, 8)
UNION
SELECT IFNULL(SUM(qa_returns.client_credit), 0)
FROM qa_returns
WHERE (DATE(qa_returns.returnlog_date) BETWEEN '12/06/25' AND '12/06/25');
I get the error:
The used SELECT statements have a different number of columns.
I'm trying to join this 2 selects with an UNION command, if we look returnlog_date and invoice_date have the same data condition, if there is any way to perform both queries into one would be better.
Use a subselect:
SELECT
COUNT(*) AS invoice_count,
IFNULL(SUM(invoice_total), 0) AS invoice_total,
IFNULL(SUM(invoice_discount), 0) AS invoice_discount,
(
SELECT IFNULL(SUM(qa_returns.client_credit), 0)
FROM qa_returns
WHERE qa_returns.returnlog_date >= '2012-06-25'
AND qa_returns.returnlog_date < '2012-06-26'
) AS client_credit
FROM qa_invoices
WHERE invoice_date >= '2012-06-25'
AND invoice_date < '2012-06-26'
AND status_code IN (5, 8)
The error is telling you exactly what the problem is, for a UNION you have to have the same number of columns in each query.
I am not sure which column in your second query corresponds to your first query, but you can insert a zero in your second query.
Something like this:
SELECT COUNT(*) AS invoice_count
, IFNULL(SUM(qa_invoices.invoice_total), 0) AS invoice_total
, IFNULL(SUM(qa_invoices.invoice_discount) ,0) AS invoice_discount
FROM qa_invoices
WHERE (DATE(qa_invoices.invoice_date) BETWEEN '12/06/25' AND '12/06/25')
AND qa_invoices.status_code IN (5, 8)
UNION
SELECT 0
, IFNULL(SUM(qa_returns.client_credit), 0)
, 0
FROM qa_returns
WHERE (DATE(qa_returns.returnlog_date) BETWEEN '12/06/25' AND '12/06/25');
Result set you union together have to have the exact same columns.
Well in order to do a UNION u need to have same number of columns