mysql UNION result has less rows than sum of table row counts - mysql

I'm using UNION to get all names in different tables.
my tables has about 10000 rows all together.
but the query returns 468 rows!!
My query is:
SELECT name FROM `shopping`
UNION
SELECT name FROM stores
UNION
SELECT name FROM concert
UNION
SELECT val AS name FROM event
UNION
SELECT name FROM fastfood
Where is the problem?

UNION removes duplicate values. You probably want UNION ALL instead.

Related

SQL to get Union values if data exists in both the tables based on column

i have two tables (table1 and table2) with common column customer_id, with union and few filters i am getting all the values from table 1 and table2. I need only rows where both the tables have the data based on the common column customer_id. Below is the example.
The output that I need is as follows
Here's what I've tried:
SELECT customer_id,
age,
amount,
type
FROM table1
WHERE age > 5
UNION
SELECT customer_id,
age,
amount,
type
FROM table2
WHERE age > 5
Your query combines the rows of the two tables but doesn't match customers present in both. What you need to add is the condition on the "customer_id" being present in the corresponding other table:
SELECT *
FROM table1
WHERE age > 5 AND customer_id IN (SELECT customer_id FROM table2)
UNION
SELECT *
FROM table2
WHERE age > 5 AND customer_id IN (SELECT customer_id FROM table1)
You should choose between:
UNION, if you want to return unique rows between the two tables - makes an additional aggregation operation
UNION ALL, if you want to allow repeated rows between the two tables
If you don't have repeated identical rows in your tables, then you should go with the most efficient one, which is UNION ALL.

How sum certain duplicated data?

I have a list of ids, some ids can be duplicated.
How to sum values for the same id in one query?
SELECT SUM(`power`)
FROM `stats`
WHERE `template` IN (489191, 489191, 489100)
The template 489191 has power = 1 and 489100 has power = 0
so I need to get 2 as the result.
You need to join with table value data to get the desired number of rows e.g.:
select sum(stats.power)
from (
select 489191 as template union all
select 489191 union all
select 489100
) as vlist
join stats on vlist.template = stats.template
If you're using MySQL 8 or later you can use the values table value constructor instead of union all:
select sum(stats.power)
from (values
row(489191),
row(489191)
row(489100)
) as vlist(template)
join stats on vlist.template = stats.template

Redshift nested json extraction

I have a table with two columns, one column named user, one json column named js that looks like this:
{"1":{"partner_id":54,"provider_id":13},
"2":{"partner_id":56,"provider_id":8},
"3":{"partner_id":2719,"provider_id":274}}
I want to select all 'provider_id' in one column/row.So it should look like this:
user| provider_ids
0001| 13,8,274
0002| 21,36,57,12
How can I do this? Thanks in advance!
Your provided json format is not so easy to work with.
Crated table for test purposes:
create table json_test as
select '0001' as usr, '{"1":{"partner_id":54,"provider_id":13},
"2":{"partner_id":56,"provider_id":8},
"3":{"partner_id":2719,"provider_id":274}}'
as json_text
union all
select '0002' as usr, '{"1":{"partner_id":54,"provider_id":21},
"2":{"partner_id":56,"provider_id":36},
"2":{"partner_id":56,"provider_id":57},
"3":{"partner_id":2719,"provider_id":12}}'
as json_text;
Query to return results:
with NS AS (
select 1 as n union all
select 2 union all
select 3 union all
select 4 union all
select 5 union all
select 6 union all
select 7 union all
select 8 union all
select 9 union all
select 10
)
select usr,
listagg(trim(TRIM(split_part(SPLIT_PART(js.json_text, '},', NS.n),'"provider_id":',2)),'}'),',') within group(order by null) AS t
from NS
join json_test js ON true and NS.n <= REGEXP_COUNT(js.json_text, '\\},') + 1
group by usr;
Notes:
1) do not name column "user" as it is reserved keyword
2) add as many dummy rows in NS subquery as there is maximum of json provider records
3) Yes, I know, this isn't very readable SQL :D

Count users and groups totals in one query

I am super new to access and having difficulty with a query. My table (tblpacks) is the following:
id user_id group_id quota_id
1 1 1 1
2 1 2 1
3 2 1 1
4 3 1 1
Ideally, what I now is to get hte number of unique users and groups for quota_id=1
The result will be:
total_users = 3
total_groups = 2
If you only wanted to count one field, there would by a simple solution, but since you want to count 2 separate fields, you in fact need at least 2 separate queries.
My answer is to use a UNION query as the source for counting. This UNION query returns the distinct user_id values (with Null as group_id) and the distinct group_id values (with Null as user_id). I omitted the DISTINCT keyword, because UNION (without ALL) does a DISTINCT query automatically. As the datatypes where not recognized correctly when using a constant Null field in the first SELECT statement of the UNION query, I added a third SELECT statement as the first one, which selects both fields from the table but returns no records:
SELECT Count(user_id) AS total_users, Count(group_id) AS total_groups
FROM (
SELECT user_id, group_id FROM tblpacks WHERE Yes=No
UNION
SELECT user_id, Null FROM tblpacks WHERE quota_id=1
UNION
SELECT Null, group_id FROM tblpacks WHERE quota_id=1
) AS qsub;

Inserting duplicate records based on a value without using cursor

I had a problem in database. I have to insert duplicate records of a particular record on a another table based on a value.
First i used cursor to fetch each records and get the number of duplication i wants and after that used another cursor for duplication. Everything worked fine. But if the records in more than 500, i went dead slow. Then i did some research and found a way to insert without cursor.
INSERT INTO report(id, Name)
SELECT i.id,i.Name FROM (SELECT 1 AS id
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 10) AS o
INNER JOIN table i WHERE o.id<=i.frequence;
where frequence is the number of duplication. Please drop your idea to improve your query.
You could try creating a table with a record for each value from 1 to 10 and then join to that. I'm not sure it would be any faster though. You would have to experiment with it.
In this example the table with the values from 1 to 10 is called "dup" and the field containing these values is called "id".
INSERT INTO report(id, Name)
SELECT i.id, i.Name
FROM table i
JOIN dup d
ON d.id <= i.frequence;
If you have any table that contains a row number that goes at least as high as the maximum frequence, you could to this:
INSERT INTO report(id, Name)
SELECT i.id,i.Name FROM table i
inner join (
select distinct some_row_number_column from some_table
) o on o.some_row_number_column <= i.frequence;
This is basically the same as what you were doing, but it avoids the messy union all statements.
Or you could make a cursor that inserts numbers from 1 to the maximum frequence into a temporary table, then use that in your join. Or you could use a row numbering variable to generate the necessary sequence. Basically, do anything that will generate a list of consecutive numbers from 1 to the maximum that you need.
I would normally use recursion for this (DB2 syntax):
INSERT INTO report(id, Name)
with num_list (num) as (
values (1)
union all
select num + 1 from num_list
where num < (select max(frequence) from table)
)
SELECT i.id,i.Name FROM table i
inner join num_list on num_list.num <= i.frequence;
However, MySQL doesn't support recursion, apparently.