MySQL combine results from UNION of same-scheme tables - mysql

There are two tables with the same structure: 'imsc_storage_users' & 'imsc_storage_users_archive'.
My current SELECT/UNION:
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION DISTINCT
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`
ORDER BY `correct` DESC,`minutes` ASC
I'm getting these results:
+--------------+---------------------+-----------+---------+---------+------+---------+
| cli | ts | questions | answers | correct | last | minutes |
+--------------+---------------------+-----------+---------+---------+------+---------+
| 111111111111 | 2011-12-22 11:13:57 | 30 | 29 | 14 | 30 | 1305.47 |
| 222222222222 | 2011-12-15 13:39:16 | 26 | 24 | 13 | 24 | 15.67 |
| 333333333333 | 2011-12-15 13:39:39 | 26 | 25 | 11 | 25 | 15.18 |
| 444444444444 | 2011-12-15 13:39:39 | 25 | 21 | 11 | 25 | 280.53 |
| 111111111111 | 2011-12-22 11:13:57 | 25 | 21 | 10 | 25 | 373.87 |
| 555555555555 | 2011-12-19 15:46:15 | 11 | 10 | 5 | 10 | 3.8 |
| 666666666666 | 2011-12-15 13:39:16 | 14 | 10 | 4 | 10 | 321.64 |
| 777777777777 | 2011-12-19 08:34:36 | 15 | 11 | 4 | 13 | 474.66 |
Notice that '111111111111' appears twice?
I want it to be combined, so in the results set I get one row of '111111111111' which combines/sums all fields; 'questions' =>> 55.... etc'.
What would be the correct SQL?
Performance are NOT of an issue here.
Thank you!

SELECT `cli`,max(`ts`) AS ts, sum(`questions`) as questions, sum(`answers`) as answers,sum(`correct`) as correct,sum(`last`) as last,sum(`minutes`) as minutes
FROM (
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION ALL
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`
) AS baseview
GROUP BY cli
ORDER BY `correct` DESC,`minutes` ASC

Try:
SELECT `cli`,
`ts`,
sum(`questions`),
sum(`answers`),
sum(`correct`),
sum(`last`),
sum(`minutes`)
FROM (SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users`
UNION ALL
SELECT `cli`,`ts`,`questions`, `answers`,`correct`,`last`,`minutes`
FROM `imsc_storage_users_archive`) V
group by `cli`, `ts`
ORDER BY 5 DESC, 7 ASC

Related

Select complete record with earliest timestamp on a day for each employee [duplicate]

This question already has answers here:
Group by minimum value in one field while selecting distinct rows
(10 answers)
Closed 2 years ago.
I have a table that stores facial login data of employees based upon employee id. I need to get the earliest login for each employee on a day and all other logins to be ignored. I know how to get latest or earliest record for each employee but I am unable to figure out how to get earliest entry in each day by each employee.
+----+-----------+--------------------------------------+-------------+-----------------------+
| id | camera_id | image_name | employee_id | created_at |
+----+-----------+--------------------------------------+-------------+-----------------------+
| 10 | 2 | pjcc7vf142pec6li7k8kqxuqvnmhm0tyo8ib | 16 | 2020-07-11 10:40:20 |
| 11 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-11 10:40:22 |
| 14 | 2 | 3p74yrq35nfaazwdo8auguvn2h5hpugtfvvw | 2 | 2020-07-11 12:07:24 |
| 15 | 2 | hpa2am40ufke7o7q2y733hh83h7ykxxdgkof | 16 | 2020-07-11 12:09:35 |
| 16 | 2 | g7adgyzloab2t4z7xx2id0a9cjqx8ojfni99 | 2 | 2020-07-11 12:09:41 |
| 17 | 2 | tapufkiuj5toxfdoikjicbe3k7tl32yj5khp | 16 | 2020-07-12 12:09:47 |
| 18 | 2 | pjcc7vf142pec6li7k8kqxuqvnmhm0tyo8ib | 16 | 2020-07-12 14:40:20 |
| 19 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-12 15:40:22 |
| 20 | 2 | 3p74yrq35nfaazwdo8auguvn2h5hpugtfvvw | 2 | 2020-07-12 16:07:24 |
| 21 | 2 | hpa2am40ufke7o7q2y733hh83h7ykxxdgkof | 16 | 2020-07-12 17:09:35 |
| 22 | 2 | g7adgyzloab2t4z7xx2id0a9cjqx8ojfni99 | 2 | 2020-07-13 12:09:41 |
+----+-----------+--------------------------------------+-------------+-----------------------+
The result will look like below...
+----+-----------+--------------------------------------+-------------+-----------------------+
| id | camera_id | image_name | employee_id | created_at |
+----+-----------+--------------------------------------+-------------+-----------------------+
| 10 | 2 | pjcc7vf142pec6li7k8kqxuqvnmhm0tyo8ib | 16 | 2020-07-11 10:40:20 |
| 11 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-11 10:40:22 |
| 17 | 2 | tapufkiuj5toxfdoikjicbe3k7tl32yj5khp | 16 | 2020-07-12 12:09:47 |
| 19 | 2 | 9iizfdtk3m81a745ut7tzqzqh8kf9ipz2u02 | 2 | 2020-07-12 15:40:22 |
| 22 | 2 | g7adgyzloab2t4z7xx2id0a9cjqx8ojfni99 | 2 | 2020-07-13 12:09:41 |
+----+-----------+--------------------------------------+-------------+-----------------------+
You can do:
select *
from t
where (employee_id, created_at) in (
select employee_id, min(created_at)
from t
group by employee_id, date(created_at)
)
how to get earliest entry in each day by each employee
You can filter with a correlated subquery:
select t.*
from mytable t
where t.created_at = (
select min(t1.created_at)
from mytable t1
where
t1.employee_id = t.employee_id
and t1.created_at >= date(t.created_at)
and t1.created_at < date(t.created_at) + interval 1 day
)
This query would take advantage of an index on (employee_id, created_at).
Or, if you are running MySQL 8.0, you can use window functions:
select *
from (
select
t.*,
row_number() over(
partition by employee_id, date(created_at)
order by created_at
) rn
from mytable t
) t
where rn = 1

MySQL - How to fetch all records from two tables with the pagination?

We have two tables credit_points and debit_points having user_id is reference. Our concern is we want to fetch all the records in a single query order by created_date DESC with limit and offset. Please find the table list and Output table.
credit_points
+----+----------+--------------+---------------------+
| id | user_id | credit_value | created_date |
+----+----------+--------------+---------------------+
| 1 | 111 | 13 | 2020-01-08 10:20:26 |
| 2 | 111 | 11 | 2020-01-09 11:20:23 |
| 3 | 111 | 7 | 2020-01-09 13:25:12 |
| 4 | 111 | 20 | 2020-01-13 12:25:17 |
+----+----------+--------------+---------------------+
debit_points
+----+----------+--------------+---------------------+
| id | user_id | debit_value | created_date |
+----+----------+--------------+---------------------+
| 1 | 111 | 13 | 2020-01-09 10:20:25 |
| 2 | 111 | 11 | 2020-01-11 11:18:54 |
| 3 | 111 | 15 | 2020-01-14 13:50:24 |
| 4 | 111 | 5 | 2020-01-14 15:23:12 |
+----+----------+------------+-----------------------+
Output should be:
+----------+--------------+---+------------------------------+
| user_id | credit_value | debit_value | created_date |
+----------+--------------+-------------+--------------------+
| 111 | NULL | 5 |2020-01-14 15:23:12 |
| 111 | NULL | 15 |2020-01-14 13:50:24 |
| 111 | 20 | NULL |2020-01-13 12:25:17 |
| 111 | NULL | 11 |2020-01-11 11:18:54 |
| 111 | 7 | NULL |2020-01-09 13:25:12 |
| 111 | 11 | NULL |2020-01-09 11:20:23 |
| 111 | NULL | 13 |2020-01-09 10:20:25 |
| 111 | 13 | NULL |2020-01-08 10:20:26 |
+----------+--------------+-------------+-----+--------------+
Query1:
SELECT
c.user_id, c.credit_value, d.debit_value, d.created_date
FROM credit_points c
RIGHT JOIN debit_points d ON(c.user_id=d.user_id)
WHERE c.user_id=111
ORDER BY c.created_date,d.created_date DESC
limit 20;
I know the above query is completely wrong. Please help me to fetch it in the right way.
Query2:
SELECT user_id,credit_value, created_date
FROM credit_points where user_id=111
UNION ALL
SELECT user_id,debit_value,created_date
FROM debit_points where user_id=111 ORDER BY created_date DESC
The above query(Query2) is working fine but we are unable to fetch the debit_value column. Both credit_value and debit_value is coming in one column.
You can combine the data from both tables into a derived table by using UNION and then execute a SELECT over it with needed offset:
SELECT * FROM
(
SELECT user_id, credit_value, NULL AS debit_value, created_date FROM muvi_credit_points
UNION ALL
SELECT user_id, NULL AS credit_value, debit_value, created_date FROM muvi_debit_points
) t
WHERE user_id = 111
ORDER BY created_date DESC
LIMIT 0, 20
Of course, the filtering by user_id could be done into internal SELECT statements if needed.

MYSQL COUNT(column) returns multiple lines unexpectedly

I have two tables:
1. SELECT * FROM gas_trades_bids;
+----+---------+----------+--------+------------+------------+
| id | user_id | claim_id | amount | lots_value | timestmp |
+----+---------+----------+--------+------------+------------+
| 5 | 9 | 11 | 60 | NULL | 1571317861 |
| 6 | 9 | 11 | 100 | NULL | 1571656888 |
| 7 | 9 | 11 | 50 | NULL | 1571727353 |
| 8 | 9 | 11 | 50 | NULL | 1571918296 |
+----+---------+----------+--------+------------+------------+
4 rows in set (0.00 sec)
2. SELECT * FROM gas_trades_offers;
+----+---------+----------+--------+------------+----------+------------+
| id | user_id | claim_id | amount | lots_value | accepted | timestmp |
+----+---------+----------+--------+------------+----------+------------+
| 8 | 9 | 11 | 33 | 22 | NULL | 1571918576 |
| 9 | 9 | 11 | 33 | 22 | 1 | 1571918576 |
| 10 | 9 | 11 | 33 | 22 | 1 | 1571918576 |
+----+---------+----------+--------+------------+----------+------------+
3 rows in set (0.01 sec)
The goals are:
Count the amount of the rows where gas_trades_bids.claim_id = gas_trades_offers_claim_id and gas_trades_bids.claim_id = 11 and gas_trades_bids.user_id = 11
Get the sum of the column gas_trades_offers.lots_value values
To reach this I tried to run:
SELECT COUNT(bids.id) amount, SUM(offers.lots_value)
FROM gas_trades_offers offers, (SELECT * FROM gas_trades_bids) bids
WHERE bids.user_id = 9
AND bids.user_id = offers.user_id
But I've got the multiple rows:'
+--------+------------------------+
| amount | SUM(offers.lots_value) |
+--------+------------------------+
| 3 | 66 |
| 3 | 66 |
| 3 | 66 |
| 3 | 66 |
+--------+------------------------+
4 rows in set (0.01 sec)
What do I do in the wrong way?
I have expected to get only:
+--------+------------------------+
| amount | SUM(offers.lots_value) |
+--------+------------------------+
| 3 | 66 |
+--------|------------------------|
I don't need to use GROUP BY!
Is it exactly what you need? Hope that this query can work well.
SELECT COUNT(offers.id) amount,
SUM(offers.lots_value)
FROM gas_trades_offers offers
WHERE offers.user_id = 9 and offers.claim_id = 11
AND exists (SELECT id FROM gas_trades_bids bids WHERE bids.claim_id = offers.claim_id and bids.user_id = offers.user_id)
Try this:
SELECT COUNT(bids.id) amount,
SUM(offers.lots_value)
FROM gas_trades_offers offers
JOIN gas_trade_bids bids ON bids.user_id = offers.user_id
WHERE offers.user_id = 9;

SQL Query to Sort the result according to maximum common results

I have a problem in making SQL query. I am making a small Search Engine in which the word to page mapping or indexes are kept like this.
Sorry I wasn't able to post images here so I tried writing the output like this.
+---------+---------+-----------+--------+
| word_id | page_id | frequency | degree |
+---------+---------+-----------+--------+
| 2331 | 29 | 2 | 1 |
| 2332 | 29 | 7 | 1 |
| 2333 | 29 | 4 | 1 |
| 2334 | 29 | 1 | 1 |
| 2335 | 29 | 1 | 1 |
| 2336 | 29 | 1 | 1 |
| 2337 | 29 | 2 | 1 |
| 2338 | 29 | 7 | 1 |
| 2343 | 29 | 1 | 3 |
| 2344 | 29 | 1 | 3 |
......
......
...... and so on.
Word_id points to Words present in other table and page_id points to URLs present in other table.
Now Suppose I want to search "Rapid 3D Prototyping Services". I brought the union of results corresponding to individual words by query ->
select * from words_detail where word_id=2353 or word_id=2364 or word_id=2709 or word_id=2710;
In above query the word_ids corresponds to the 4 words in the search query and the results are as below.
Union of page_id corresponding to individual words...
mysql>
select * from words_detail where word_id=2353 or word_id=2364 or word_id=2709 or word_id=2710;
+---------+---------+-----------+--------+
| word_id | page_id | frequency | degree |
+---------+---------+-----------+--------+
| 2353 | 29 | 2 | 4 |
| 2353 | 33 | 2 | 2 |
| 2353 | 36 | 5 | 9 |
| 2353 | 40 | 1 | 4 |
| 2353 | 41 | 1 | 9 |
| 2353 | 45 | 4 | 9 |
| 2353 | 47 | 2 | 9 |
| 2353 | 49 | 4 | 9 |
| 2353 | 52 | 1 | 4 |
| 2353 | 53 | 1 | 9 |
| 2353 | 66 | 2 | 9 |
| 2364 | 29 | 1 | 4 |
| 2364 | 34 | 1 | 4 |
| 2364 | 36 | 9 | 2 |
| 2709 | 36 | 1 | 9 |
| 2710 | 36 | 1 | 9 |
+---------+---------+-----------+--------+
16 rows in set (0.00 sec)
But I want the result to be sorted according to maximum match. The earlier result should be where all 4 words match, next result should be with 3 match and so on. In other words earlier results should have those page_id which are common to 4 word_ids, next should be those which are common in 3 words_ids and so on.
I checked here but this is not working in my case because in my case OR conditions are not matched in a single row.
How can such a query can be designed?
Use the occurence of you page_id as your matching count and then order by it.
select * from words_detail A
inner join
(SELECT PAGE_ID
, COUNT(PAGE_ID) matchCount
from words_detail
where word_id=2353 or word_id=2364 or word_id=2709 or word_id=2710
group by PAGE_ID) B
on A.PAGE_ID=B.PAGE_ID
where word_id=2353 or word_id=2364 or word_id=2709 or word_id=2710
order by matchCount desc
Try this
select p.*
from words_detail p
, (select word_id, count(1) as count
from words_detail where
word_id in (2353,2364,2709,2710) group by word_id) t
where p.word_id = t.word_id
order by t.count desc;
You can do a subquery to get the number of apperances for each page. Then you have to join the subquery with your table and you will be able to order the results by the number of page appearances.
Your final query should look like this:
SELECT *
FROM words_detail,
(
SELECT page_id,
COUNT(*) AS npages
FROM words_detail
WHERE word_id IN (2353, 2364, 2709, 2710)
GROUP BY page_id
) AS matches
WHERE words_detail.page_id = matches.page_id
AND word_id IN (2353, 2364, 2709, 2710)
ORDER BY matches.npages DESC

mysql query for rating system

select
user_id,
#pos:=(#pos+1) as new_position,
(coins+total_item_costs) as wealth
from user_ledger
join users using (user_id),(select #pos:=0) p
ORDER BY wealth DESC
limit 10;
+---------+--------------+------------+
| user_id | new_position | wealth |
+---------+--------------+------------+
| 19 | 19 | 1112823871 |
| 11 | 11 | 13318047 |
| 8 | 8 | 7292407 |
| 6 | 6 | 6122746 |
| 27 | 27 | 5271889 |
| 23 | 23 | 5263050 |
| 9 | 9 | 5171734 |
| 3 | 3 | 5136092 |
| 15 | 15 | 5097488 |
| 4 | 4 | 5089487 |
+---------+--------------+------------+
10 rows in set (0.01 sec)
The new_position is incorrect..
What's wrong, guys? :)
ps. pls dont tell me to use temporary table
Should do the ORDER BY beforehand the position.
SELECT user_id,#pos:=(#pos+1) as new_position,wealth FROM (
select user_id,(coins+total_item_costs) as wealth from user_ledger join users
using (user_id) ORDER BY wealth DESC limit 10 ) a,(select #pos:=0) p