MYSQL COUNT(column) returns multiple lines unexpectedly - mysql

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;

Related

I have a challenging MySQL SELECT query that involves stock and threshold bondary

I Have a MySQL DataBase which contains two tables linked with a foreign key:
MatPr(id, Designation, threshold_stock)
And
MvtStock_MatPr(id, Qte_Mvt, Qte_Tot,idMatPr)
What I want is to get the last Qte_tot, Designation,threshold_stock where threshold_stock>qte_tot
I tried this code and did not work:
SELECT MvtStock_MatPr.id,idMatPr, Nom, threshold_stock, Qte_Tot
FROM MvtStock_MatPr, MatPr
WHERE MatPr.id=MvtStock_MatPr.idMatPr AND threshold_stock>Qte_Tot
Here is Sample Data set:
mysql> SELECT MvtStock_MatPr.id,idMatPr, Designation, threshold_stock, Qte_Tot FROM MvtStock_MatPr, MatPr WHERE MatPr.id=MvtStock_MatPr.idMatPr AND threshold_stock>Qte_Tot ORDER
BY id,idMatPr;
| id | idMatPr | Dsignation| threshold_stock| Qte_Tot |
| 1 | 1 | bakra | 120 | 10 |
| 2 | 2 | zipper | 130 | 20 |
| 3 | 1 | bakra | 120 | 30 |
| 7 | 2 | zipper | 130 | 50 |
4 rows in set (0.00 sec)
mysql> SELECT * FROM MatPr;
| id | Designation| threshold_stock|
| 1 | bakra | 120 |
| 2 | zipper | 130 |
2 rows in set (0.00 sec)
mysql> SELECT * FROM MvtStock_MatPr;
| id | DateMvt | Qte_Mvt | Qte_Tot | idMatPr |
| 1 | 2016-01-01 | 10 | 10 | 1 |
| 2 | 2016-02-02 | 20 | 20 | 2 |
| 3 | 2016-03-03 | 20 | 30 | 1 |
| 4 | 2016-03-03 | 100 | 130 | 1 |
| 5 | 2016-03-03 | 50 | 180 | 1 |
| 6 | 2016-03-03 | 20 | 200 | 1 |
| 7 | 2016-03-05 | 30 | 50 | 2 |
7 rows in set (0.00 sec)
What I would like to get is:
| id | idMatPr | Dsignation| threshold_stock| Qte_Tot
| 3 | 1 | bakra | 120 | 30 |
| 7 | 2 | zipper | 130 | 50 |
+----+---------+--------+-------+---------+
Thanks for your contributions
Use the below query
Select m1.id,m1.idMatpr,m.threshold_stock,m.Qte_Tot
From MvtStock_Matpr m1 join Matpr m
On m1.idMatPr=m.id and m.threshold_stock>m1.Qte_Tot
I'm not sure that I completely follow what your problem is: is it selecting just one row from a result set? If so, does a subquery fix your problem?
SELECT *
FROM MatPr
WHERE ID = (
SELECT idMatPr
FROM MvtStock_MatPr, MatPr
WHERE MatPr.id = MvtStock_MatPr.idMatPr
AND threshold_stock > Qte_Tot
LIMIT 1
)
If you want to select just the rows from MatPr, does this work for you?
SELECT MatPr.*
FROM MvtStock_MatPr, MatPr
WHERE MatPr.id = MvtStock_MatPr.idMatPr
AND threshold_stock > Qte_Tot
http://sqlfiddle.com/#!9/d4ef50/2
Try this query:
select * from
( SELECT MvtStock_MatPr.id,idMatPr,Designation, threshold_stock, Qte_Tot
FROM MvtStock_MatPr join MatPr
on MatPr.id=MvtStock_MatPr.idMatPr
where threshold_stock>Qte_Tot
order by DateMvt desc
) T
group by T.idMatPr

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

How to get this specific user rankings query in mysql?

I've got tbl_items in my user database that I want to sort user rankings on a particular item with certain id (514). I have test data on my dev environment with this set of data:
mysql> select * from tbl_items where classid=514;
+---------+---------+----------+
| ownerId | classId | quantity |
+---------+---------+----------+
| 1 | 514 | 3 |
| 2 | 514 | 5 |
| 3 | 514 | 11 |
| 4 | 514 | 46 |
| 5 | 514 | 57 |
| 6 | 514 | 6 |
| 7 | 514 | 3 |
| 8 | 514 | 27 |
| 10 | 514 | 2 |
| 11 | 514 | 73 |
| 12 | 514 | 18 |
| 13 | 514 | 31 |
+---------+---------+----------+
12 rows in set (0.00 sec)
so far so good :) I wrote the following query:
set #row=0;
select a.*, #row:=#row+1 as rank
from (select a.ownerid,a.quantity from tbl_items a
where a.classid=514) a order by quantity desc;
+---------+----------+------+
| ownerid | quantity | rank |
+---------+----------+------+
| 11 | 73 | 1 |
| 5 | 57 | 2 |
| 4 | 46 | 3 |
| 13 | 31 | 4 |
| 8 | 27 | 5 |
| 12 | 18 | 6 |
| 3 | 11 | 7 |
| 6 | 6 | 8 |
| 2 | 5 | 9 |
| 7 | 3 | 10 |
| 1 | 3 | 11 |
| 10 | 2 | 12 |
+---------+----------+------+
12 rows in set (0.00 sec)
that ranks correctly the users. However in a table with lots of records, I need to do the following:
1) be able to get small portion of the list, around where the user ranking actually resides, something that would get me the surrounding records, preserving the overall rank:
I tried to do these things with setting a user variable to the ranking of the current user and by using offset and limit, but couldn't preserve the overall ranking.
This should get me something like the following (for instance ownerId=2 and surroundings limit 5:
+---------+----------+------+
| ownerid | quantity | rank |
+---------+----------+------+
| 3 | 11 | 7 |
| 6 | 6 | 8 |
| 2 | 5 | 9 | --> ownerId=2
| 7 | 3 | 10 |
| 1 | 3 | 11 |
+---------+----------+------+
5 rows in set (0.00 sec)
2) I'd also need another query (preferably single query) that gets me the top 3 places + the ranking of particular user with certain id, preferably with a single query, no matter if he's among the top 3 places or not. I couldn't get this as well
It would look like the following (for instance ownerId=2 again):
+---------+----------+------+
| ownerid | quantity | rank |
+---------+----------+------+
| 11 | 73 | 1 |
| 5 | 57 | 2 |
| 4 | 46 | 3 |
| 2 | 5 | 9 | --> ownerId=2
+---------+----------+------+
4 rows in set (0.00 sec)
Also I'm in a bit of a concern about the performance of the queries on a table with millions of records...
Hope someone helps :)
1) 5 entries around a given id.
set #row=0;
set #rk2=-1;
set #id=2;
select b.* from (
select a.*, #row:=#row+1 as rank, if(a.ownerid=#id, #rk2:=#row, -1) as rank2
from (
select a.ownerid,a.quantity
from tbl_items a
where a.classid=514) a
order by quantity desc) b
where b.rank > #rk2 - 3
limit 5;
Though you'll get an extra column rank2: you probably want to filter it out by explicit list of columns instead of b.*. Maybe it's possible whith a having clause rather than an extra nesting.
2) 3 top ranked entries + 1 specific id
select b.* from (
select a.*, #row:=#row+1 as rank
from (
select a.ownerid,a.quantity
from tbl_items a
where a.classid=514) a
order by quantity desc) b
where b.rank < 4 or b.ownerid=#id

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

MySQL combine results from UNION of same-scheme tables

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