I have 2 tables
requests
requests_votes
request structure is:
id | req_name | content | hits
------------------------------
1 | Sample | Some | NULL
2 | Sample | Some | NULL
3 | Sample | Some | NULL
4 | Sample | Some | NULL
5 | Sample | Some | NULL
requests_votes structure is:
id | requestid | user_id
------------------------
10 | 2 | 2556
18 | 2 | 2522
33 | 3 | 120
44 | 2 | 1559
98 | 5 | 253
width the following query im able to calculate how votes have an item(request)
SELECT `requestid` , count( requests_votes.id ) AS totals
FROM `requests_votes`
INNER JOIN `requests` ON requests.id = requests_votes.requestid
GROUP BY `requestid`
output:
requestid | totals
------------------
2 | 3
3 | 1
5 | 1
i want to populate the hits column inside requests table with count( requests_votes.id ) result.
I've go trough the similar questions asked here on stackoverflow, but couldn't find the solution.
You can use JOIN in an UPDATE query:
UPDATE `requests` T1 JOIN
(SELECT `requestid` , count( requests_votes.id ) AS totals
FROM `requests_votes`
INNER JOIN `requests` ON requests.id = requests_votes.requestid
GROUP BY `requestid`) T2 ON T1.id=T2.requestid
SET T1.hits=T2.totals
Related
I have database table like
transactions
-----------
id
code
date
amount
formalities
-----------
id
transaction_id
this is query to get max value of transactions
SELECT MAX(transaction_id) FROM `transactions` n LEFT JOIN `formalities` r ON r.transaction_id = n.id
But what I want to achieve here is to get the max value of id group by transactions code, but the value must check if the transactions have relation to formalities or not.
If yes, get max value where they relate.
If not just get the usual max value.
Is there a query to achieve something like this?
example:
transactions
--------------------
id | code | amount |
1 | ABC | 10000 |
2 | ABC | 20000 |
3 | KOO | 10000 |
4 | ABC | 20000 |
5 | KOO | 30000 |
6 | KOO | 10000 |
formalities
-----------
id | transaction_id |
1 | 3 |
2 | 5 |
The result I want is getting the following output from the transactions table
id
--
4
5 ( priority the one that have relation and get the max value)
Use a LEFT JOIN and get both - MAX(transactions.id) and MAX(formalities.transaction_id):
select t.code, max(f.transaction_id), max(t.id)
from transactions t
left join formalities f on f.transaction_id = t.id
group by t.code
The result would be
| code | max(f.transaction_id) | max(t.id) |
| ---- | --------------------- | --------- |
| ABC | NULL | 4 |
| KOO | 5 | 6 |
View on DB Fiddle
To "prioritize" transaction_id column from formalities table you can use COALESCE(), which will return the first non NULL value:
select t.code, coalesce(max(f.transaction_id), max(t.id)) as max_transaction_id
from transactions t
left join formalities f on f.transaction_id = t.id
group by t.code
Result:
| code | max_transaction_id |
| ---- | ------------------ |
| ABC | 4 |
| KOO | 5 |
View on DB Fiddle
I am not sure if I am getting the question right, but why don't you simply use -
SELECT MAX(transaction_id) FROM `transactions` n INNER JOIN `formalities` r ON r.transaction_id = n.id group by n.code
I'm trying to select all rows in this table, with the constraint that revised id's are selected instead of the original ones. So, if a row has a revision, that revision is selected instead of that row, if there are multiple revision numbers the highest revision number is preferred.
I think an example table, output, and query will explain this better:
Table:
+----+-------+-------------+-----------------+-------------+
| id | value | original_id | revision_number | is_revision |
+----+-------+-------------+-----------------+-------------+
| 1 | abcd | null | null | 0 |
| 2 | zxcv | null | null | 0 |
| 3 | qwert | null | null | 0 |
| 4 | abd | 1 | 1 | 1 |
| 5 | abcde | 1 | 2 | 1 |
| 6 | zxcvb | 2 | 1 | 1 |
| 7 | poiu | null | null | 0 |
+----+-------+-------------+-----------------+-------------+
Desired Output:
+----+-------+-------------+-----------------+
| id | value | original_id | revision_number |
+----+-------+-------------+-----------------+
| 3 | qwert | null | null |
| 5 | abcde | 1 | 2 |
| 6 | zxcvb | 2 | 1 |
| 7 | poiu | null | null |
+----+-------+-------------+-----------------+
View Called revisions_max:
SELECT
responses.original_id AS original_id,
MAX(responses.revision_number) AS revision
FROM
responses
WHERE
original_id IS NOT NULL
GROUP BY responses.original_id
My Current Query:
SELECT
responses.*
FROM
responses
WHERE
id NOT IN (
SELECT
original_id
FROM
revisions_max
)
AND
is_revision = 0
UNION
SELECT
responses.*
FROM
responses
INNER JOIN revisions_max ON revisions_max.original_id = responses.original_id
AND revisions_max.revision_number = responses.revision_number
This query works, but takes 0.06 seconds to run. With a table of only 2000 rows. This table will quickly start expanding to tens or hundreds of thousands of rows. The query under the union is what takes most of the time.
What can I do to improve this queries performance?
How about using coalesce()?
SELECT COALESCE(y.id, x.id) AS id,
COALESCE(y.value, x.value) AS value,
COALESCE(y.original_id, x.original_id) AS original_id,
COALESCE(y.revision_number, x.revision_number) AS revision_number
FROM responses x
LEFT JOIN (SELECT r1.*
FROM responses r1
INNER JOIN (SELECT responses.original_id AS
original_id,
Max(responses.revision_number) AS
revision
FROM responses
WHERE original_id IS NOT NULL
GROUP BY responses.original_id) rev
ON r1.original_id = rev.original_id
AND r1.revision_number = rev.revision) y
ON x.id = y.original_id
WHERE y.id IS NOT NULL
OR x.original_id IS NULL;
The approach I would take with any other DBMS is to use NOT EXISTS:
SELECT r1.*
FROM Responses AS r1
WHERE NOT EXISTS
( SELECT 1
FROM Responses AS r2
WHERE r2.original_id = COALESCE(r1.original_id, r1.id)
AND r2.revision_number > COALESCE(r1.revision_number, 0)
);
To remove any rows where a higher revision number exists for the same id (or original_id if it is populated). However, in MySQL, LEFT JOIN/IS NULL will perform better than NOT EXISTS1. As such I would rewrite the above as:
SELECT r1.*
FROM Responses AS r1
LEFT JOIN Responses AS r2
ON r2.original_id = COALESCE(r1.original_id, r1.id)
AND r2.revision_number > COALESCE(r1.revision_number, 0)
WHERE r2.id IS NULL;
Example on DBFiddle
I realise that you have said that you don't want to use LEFT JOIN and check for nulls, but I don't see that there is a better solution.
1. At least this was the case historically, I don't actively use MySQL so don't keep up to date with developments in the optimiser
I have a table called tbl_chat and tbl_post.
The tbl_chat is given as follows.
|--------------------------------------------------------------------------------|
| chat_id | message | from_user | to_user | post_id |send_date |
|--------------------------------------------------------------------------------|
| 1 | Hi | 23 | A | 35 | 2016-04-01 17:35|
| 2 | Test | 24 | A | 35 | 2016-04-02 01:35|
| 3 | Thut | A | 23 | 35 | 2016-04-02 03:35|
| 4 | test | A | 24 | 35 | 2016-04-02 12:35|
| 5 | Hi | 23 | A | 35 | 2016-04-03 17:35|
|--------------------------------------------------------------------------------|
Now, in the chat table we can see three users are interacting with each other. The Admin (A), user with id = 23 and user = 24.
So there is basically two chat thread.
One between A and 23
Another between A and 24.
I want a query which will show the two chat threads, with the last chat message. Just like in case of facebook chat list showing all the chat-threads with mentioning the last chat.
I am writing a query like this.
SELECT * FROM tbl_chat, tbl_post
WHERE tbl_post.post_id = tbl_chat.post_id
AND tbl_post.post_id = '39'
GROUP BY tbl_chat.chat_from
ORDER BY date DESC
The query has a problem. It is first retrieving all the chats and grouping it w.r.t. chat_from and then ORDERING it Descending-wise.
So first it's creating the group, and then ordering the group.
Also, the first query produces three group, taking the reply message from Admin as a separate group. Since GROUP BY chat_from.
How can I solve this issue?
EDIT:-
I would be grateful if someone can build the query in Active-Records of Codeigniter.
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(chat_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,message VARCHAR(20) NOT NULL
,from_user VARCHAR(12)
,to_user VARCHAR(12)
,post_id INT NOT NULL
,send_date DATETIME NOT NULL
);
INSERT INTO my_table VALUES
(1,'Hi' ,'23','A' ,35,'2016-04-01 17:35:00'),
(2,'Test','24','A' ,35,'2016-04-02 01:35:00'),
(3,'Thut','A' ,'23',35,'2016-04-02 03:35:00'),
(4,'test','A' ,'24',35,'2016-04-02 12:35:00'),
(5,'Hi' ,'23','A' ,35,'2016-04-03 17:35:00');
SELECT a.*
FROM my_table a
JOIN
( SELECT LEAST(from_user,to_user) user1
, GREATEST(from_user,to_user) user2
, MAX(send_date) send_date
FROM my_table
GROUP
BY user1
, user2
) b
ON b.user1 = LEAST(a.from_user,a.to_user)
AND b.user2 = GREATEST(a.from_user,a.to_user)
AND b.send_date = a.send_date;
+---------+---------+-----------+---------+---------+---------------------+
| chat_id | message | from_user | to_user | post_id | send_date |
+---------+---------+-----------+---------+---------+---------------------+
| 4 | test | A | 24 | 35 | 2016-04-02 12:35:00 |
| 5 | Hi | 23 | A | 35 | 2016-04-03 17:35:00 |
+---------+---------+-----------+---------+---------+---------------------+
You can use NOT EXISTS() :
SELECT * FROM tbl_chat
INNER JOIN tbl_post
ON tbl_post.post_id = tbl_chat.post_id
WHERE NOT EXISTS(SELECT 1 FROM tbl_chat s
WHERE tbl_chat.from_user IN(s.from_user,s.to_user)
AND tbl_chat.to_user IN(s.from_user,s.to_user)
AND tbl_chat.date < s.date)
Although date field looks like DATE type, which is curious - how would you find the difference between two messages at the same day?
I have 4 tables:
secu_content
| id | created | modified |
| 910 | 26/12/1982 | 28/12/1984 |
| 911 | 24/12/1982 | 25/12/1984 |
secu_data
| element_id | field_id | data |
| 1 | 1 | 25/12/1984 |
| 2 | 1 | 26/12/1984 |
| 3 | 1 | 27/12/1984 |
| 4 | 1 | 25/12/1984 |
| 4 | 2 | google.com |
secu_elements
| id | item_id |
| 1 | 891 |
| 2 | 711 |
| 3 | 204 |
| 4 | 911 |
secu_fields
| id | type |
| 1 | date |
| 2 | input |
Table secu_content, contains many articles, where the id is the article id.
The other 3 tables gives additional information and I want to join them.
I want to get results that includes all secu_content rows and all the columns + calc_date + calc_link
calc_date <- the data column from secu_data where field_id=1 (see secu_fields)
calc_link <- the data column from secu_data where field_id=2 (see secu_fields)
The problem is that I get 2 rows where secu_content id=911 (one row with the correct calc_date and second row with the correct calc_link), and I need one row with both.
This is my SQL:
SELECT a.id
, a.created
, a.modified
, fe.item_id AS calc_date_item_id
, fd.data AS calc_date
, CASE WHEN fd.data IS NOT NULL AND ff.type = "date" THEN fd.data
WHEN a.modified = '0000-00-00 00:00:00' THEN a.created ELSE a.modified
END as calc_date
, CASE WHEN fd.data IS NOT NULL AND ff.type = "input" THEN fd.data
END as calc_link
FROM secu_content AS a
LEFT
JOIN secu_fieldsandfilters_elements AS fe
ON fe.item_id = a.id
AND fe.content_type_id=1
LEFT
JOIN secu_fieldsandfilters_data AS fd
ON fd.element_id = fe.id
LEFT
JOIN secu_fieldsandfilters_fields as ff
ON ff.id = fd.field_id
ORDER BY a.id DESC;
Thanks in advance
Israel
Fast and dirty solution is to use second join to secu_data like that (simplified, add logic you need)
SELECT id, d1.data as `calc_date`, d2.data as `calc_link`
FROM secu_content
LEFT JOIN secu_data d1 ON secu_content.id = d1.element_id AND field_id = 1
LEFT JOIN secu_data d2 ON secu_content.id = d2.element_id AND field_id = 2
i have two tables
td_sell
|----------|----------------|------------------|
| id | user_id | price |
|----------------------------------------------|
| 1 | 2 | 10 |
|----------------------------------------------|
| 2 | 1 | 5 |
|----------------------------------------------|
| 3 | 2 | 3 |
|----------------------------------------------|
and td_commsion
|----------|----------------|------------------|
| id | user_id | price |
|----------------------------------------------|
| 1 | 1 | 3 |
|----------------------------------------------|
| 2 | 1 | 5 |
|----------------------------------------------|
| 3 | 2 | 3 |
|----------------------------------------------|
now i want a sql query like this
SELECT (SUM(td_sell.price) + SUM(td_comission.price)) AS his_earning
FROM td_sell, td_comission
WHERE td_sell.user_id='1'
AND td_comission.user_id='1'
but its showing abnormal result
the result should be 13, but its showing 29
This will work:
SELECT (SELECT SUM(s.price) FROM td_sell s WHERE s.user_id = 1)
+
(SELECT SUM(c.price) FROM td_comission c WHERE c.user_id = 1)
DEMO: SqlFiddle
You are getting the sum of the Cartesian join of the two tables.
http://en.wikipedia.org/wiki/Cartesian_product
SELECT sum(price)
FROM (
SELECT * FROM td_sell
UNION ALL
SELECT * FROM td_commission
) a
where a.user_id=1
Here's a SQL Fiddle:
Fiddle
You need to do the sum separately on each table, before combining the results. Here is one way:
select (sell + commission) as his_earning
from (select SUM(td_sell.price) as sell
from td_sell
where td_sell.user_id='1'
) s cross join
(select SUM(td_comission.price) as commission
from td_comission
where td_comission.user_id='1'
) c