SQL INSERT or UPDATE in statements - mysql

I'm new to SQL and I want to create an INSERT or Update query for my webpage. I have two buttons, Status and Shipped, next to every item. If the user presses one of these buttons, it calls a php file with a query. But I really dont know how to put together these 2 queries into 1.
Items
STATUS
SHIPPED
Item1
STATUS
SHIPPED
Item2
STATUS
SHIPPED
Item3
STATUS
SHIPPED
Status Button
IF status NOT EXIST WHERE user_id = 17 AND item_id = 5
THEN INSERT INTO table1 VALUE (status = 1) WHERE user_id = 17 AND item_id = 5
BUT, IF shipped = 1 AND status = 0 WHERE user_id = 17 AND item_id = 5
THEN UPDATE table1 SET status = 1
Shipped Button
IF shipped NOT EXIST WHERE user_id = 17 AND item_id = 5
THEN INSERT INTO table1 VALUE (shipped = 1) WHERE user_id = 17 AND item_id = 5
BUT, IF staus = 1 AND shipped = 0 WHERE user_id = 17 AND item_id = 5
THEN UPDATE table1 SET shipped = 1
Query to filter out non essecial rows
IF status = 0 AND shipped = 0 WHERE user_id = 17 AND item_id = 5
THEN DELETE row WHERE user_id = 17 AND item_id = 5
Thank you!

Related

Fetch users which have only status = 1 - Mysql query on same column

I want a list of user_id which shouldn't have zero status.
Lets say, I have task table with user id, status. I'm trying to write a query to fetch user ids which have status = 1 only but not 2. As for below table, it should get me users id of tables with only status =1;
User table
id
etc
100
anything
200
anything
300
anything
Tasks table:
id
user_id
status
1
100
1
2
100
2
3
200
2
4
300
1
5
200
2
6
300
1
I have tried this query
SELECT user_id FROM tasks where status =2 and status != 1;
The above user id 100 has two tasks one with status 1 and other with status 2, I don't want that user.
The above user id 200 has two tasks but none of them has status 1, that is what i want.
The above user id 300 has both tasks with status 1, I don't want it too.
Status 1 means open. So I want a query which should get me users with zero open tasks only. If it has status 1 and 2 both, I don't want that.
I have tried multiple queries, but unable to find it.
Using sub queries with IN()/NOT IN() you can build a list of users having tasks in status 1/2 and filter your users based on those lists:
SELECT *
FROM users
WHERE
-- ensure the user has at least 1 task in status 1
id IN(
SELECT user_id
FROM tasks
WHERE status = 1
)
-- ensure the user has no task in status 2
AND id NOT IN(
SELECT user_id
FROM tasks
WHERE status = 2
)
I have task table with user id, status. I'm trying to write a query to fetch user ids which have status = 1 only but not 2
SELECT *
FROM users
WHERE EXISTS ( SELECT NULL
FROM tasks
WHERE users.id = tasks.user_id
AND statis IN (1) -- must have 1
)
AND NOT EXISTS ( SElECT NULL
FROM tasks
WHERE users.id = tasks.user_id
AND statis IN (2) -- must not have 2
)
To test multiple values put according list to according WHERE .. AND statis IN (..) list.

MySQL Putting in duplicate id's

I'm trying to run an UPDATE query that uses the same table and I'm getting an error saying "1093 - Table 'queues_monitor_times' is specified twice, both as a target for 'UPDATE' and as a separate source for data".
UPDATE queues_monitor_times
SET queue_id = IF((
SELECT id
FROM queues_monitor_times
INNER JOIN(
SELECT pcc_group, pcc, gds, queue, category, `name`
FROM queues_monitor_times
GROUP BY pcc_group, pcc, gds, queue, category, `name`
HAVING COUNT(id) > 1
)temp ON queues_monitor_times.pcc_group = temp.pcc_group AND
queues_monitor_times.pcc = temp.pcc AND
queues_monitor_times.gds = temp.gds AND
queues_monitor_times.queue = temp.queue AND
queues_monitor_times.category = temp.category AND
queues_monitor_times.`name` = temp.`name`), 1, id)
WHERE
id NOT IN (SELECT MIN(id) FROM queues_old GROUP BY pcc_group, pcc, gds, queue, category, `name`);
I ran the select query by itself and it showed all the rows that were duplicates, which is what I wanted. I want queue_id to be set with the lowest duplicate row's id if the row is a duplicate or the row id if it is not.
Example of what the query should do:
id dup_id name value
1 1 John 13
2 2 John 13
3 3 Sally 6
4 4 Frank 4
5 5 Sally 6
And after running the query it will turn into
id dup_id name value
1 1 John 13
2 1 John 13
3 3 Sally 6
4 4 Frank 4
5 3 Sally 6
Please advise and thank you for your help.
I was able to solve my problem. Thanks for all your help!
UPDATE queues_monitor_times
SET queue_id = (
SELECT
id
FROM
queues_old
WHERE
queues_old.pcc_group = queues_monitor_times.pcc_group
AND queues_old.pcc = queues_monitor_times.pcc
AND queues_old.gds = queues_monitor_times.gds
AND queues_old.queue = queues_monitor_times.queue
AND queues_old.category = queues_monitor_times.category
AND queues_old.`name` = queues_monitor_times.`name`
GROUP BY pcc_group, pcc, gds, queue, category, `name`
HAVING COUNT(id) > 1)
WHERE
id NOT IN (SELECT MIN(id) FROM queues_old GROUP BY pcc_group, pcc, gds, queue, category, `name`);
For those that will want to use this in the future, queues_monitor_times table and queues_old table have the exact same data.

Conditional condition in ON clause

I am trying to apply a conditional condition inside ON clause of a LEFT JOIN. What I am trying to achieve is somewhat like this:
Pseudo Code
SELECT * FROM item AS i
LEFT JOIN sales AS s ON i.sku = s.item_no
AND (some condition)
AND (
IF (s.type = 0 AND s.code = 'me')
ELSEIF (s.type = 1 AND s.code = 'my-group')
ELSEIF (s.type = 2)
)
I want the query to return the row, if it matches any one of the conditions (Edit: and if it matches one, should omit the rest for the same item).
Sample Data
Sales
item_no | type | code | price
1 0 me 10
1 1 my-group 12
1 2 14
2 1 my-group 20
2 2 22
3 2 30
4 0 not-me 40
I want the query to return
item_no | type | code | price
1 0 me 10
2 1 my-group 20
3 2 30
Edit: The sales is table is used to apply special prices for individual users, user groups, and/or all users.
if type = 0, code contains username. (for a single user)
if type = 1, code contains user-group. (for users in a group)
if type = 2, code contains empty-string (for all users).
Use the following SQL (assumed, the the table sales has a unique id field as usual in yii):
SELECT * FROM item AS i
LEFT JOIN sales AS s ON i.sku = s.item_no
AND id = (
SELECT id FROM sales
WHERE item_no = i.sku
AND (type = 0 AND code = 'me' OR
type = 1 AND code = 'my-group' OR
type = 2)
ORDER BY type
LIMIT 1
)
Try following -
SELECT *,SUBSTRING_INDEX(GROUP_CONCAT(s.type ORDER BY s.type),','1) AS `type`, SUBSTRING_INDEX(GROUP_CONCAT(s.code ORDER BY s.type),','1) AS `code`,SUBSTRING_INDEX(GROUP_CONCAT(s.price ORDER BY s.type),','1) AS `price`
FROM item AS i
LEFT JOIN sales AS s
ON i.sku = s.item_no AND (SOME CONDITION)
GROUP BY i.sku

Get the last message for each thread

SQL Fiddle
http://sqlfiddle.com/#!2/1c5fc3/1
I am trying to create simple messaging system, but I am having trouble with the desired results from the SQL queries.
Here are the tables I have; I am trying to get INBOX data..
INBOX Definiton for this problem:
This should be threaded display in inbox, ie. google mail, but only to show the last message in that thread with the user who originaly created the thread and the last user who replied in the thread, if the last user is the same user that created the thread and there are no replies in beetween the message doesnt belog in inbox.
TABLES:
THREAD
id_thread
id_last_message
id_user_inital
id_user_last
THREAD_USERS
id
id_thread
id_user
THREAD_MESSAGES
id_thread_messages
id_user_sender
id_thread
datetime
subject
body
MESSAGE_STATUS
id_messsage_status
id_thread_messages
id_user
status
datetime
My logic is:
once a message has been sent
THREAD
id_thread id_last_message id_user_inital id_user_last
1 1 1 1
THREAD_USERS
id id_thread id_user
1 1 1
2 1 2
THEREAD_MESSAGES
id_thread_messages id_user_sender id_thread datetime subject body
1 1 1 07.09.2014 16:02 'title' 'text message'
MESSAGE_STATUS
id_message_status id_thread_messages id_user status datetime
1 1 1 4 07.09.2014 16:02
2 1 2 1 07.09.2014 16:02
Lets say status can be
0 = deleted (do not show at all)
1 = new (show only to user that is on the receiving end)
2 = read (this status will be shown to all users in the thread)
3 = replied (show only to user that makes this action)
4 = sent (show only to user that makes this action)
Query :
SELECT *
FROM thread
JOIN thread_users
ON thread.id_thread = thread_users.id_thread
JOIN thread_messages
ON thread.id_thread = thread_messages.id_thread
JOIN message_status
ON thread_messages.id_thread_messages = message_status.id_thread_messages
WHERE
thread_users.id_user = 2
AND message_status.status != 0
AND message_status.status != 4
AND thread.id_user_last != message_status.id_user
sample data
THREAD
id_thread id_last_message id_user_inital id_user_last
1 4 1 2
2 2 3 3
3 3 4 4
THREAD_USERS
id id_thread id_user
1 1 1
2 1 2
3 2 3
4 2 2
5 3 4
6 3 2
THEREAD_MESSAGES
id_thread_messages id_user_sender id_thread datetime subject body
1 1 1 07.09.2014 16:02 'title' 'text message'
2 3 2 07.09.2014 16:05 'hey two' 'foo'
3 4 2 07.09.2014 16:07 'hey two' 'bar'
4 2 1 07.09.2014 16:10 'title' 'replay on 1st'
MESSAGE_STATUS
id_message_status id_thread_messages id_user status datetime
1 1 1 4 07.09.2014 16:02
2 1 2 1 07.09.2014 16:02
3 2 3 4 07.09.2014 16:05
4 2 2 1 07.09.2014 16:05
5 3 4 4 07.09.2014 16:07
6 3 2 1 07.09.2014 16:07
7 4 2 4 07.09.2014 16:10
8 4 1 1 07.09.2014 16:10
How would you extract INBOX data from this situation, as I am spinning in circles for hours and can't quite get what I am doing wrong.
Thank you.
Updated solution after taking into account explanations for message status:
SELECT DISTINCT t.*, tm.* , ms.*
FROM thread t
-- tm should be last message
INNER JOIN thread_messages tm ON t.id_thread = tm.id_thread
INNER JOIN message_status ms ON (ms.id_thread_messages = tm.id_thread_messages)AND
(ms.id_user=2)AND
(ms.status!=0)
-- try to find message after tm, and then in WHERE filter only those cases where there is no message after tm
LEFT JOIN thread_messages tm_next
INNER JOIN message_status ms_next ON (ms_next.id_thread_messages = tm_next.id_thread_messages)AND
(ms_next.id_user=2)AND
(ms_next.status!=0)
ON (t.id_thread = tm_next.id_thread)and
(tm_next.datetime>tm.datetime)
LEFT JOIN thread_messages tm_other
INNER JOIN message_status ms_other ON (ms_other.id_thread_messages = tm_other.id_thread_messages)AND
(ms_other.id_user=2)AND
(ms_other.status!=0)
ON (t.id_thread = tm_other.id_thread)and
(tm_other.id_thread_messages!=tm.id_thread_messages)and
(tm_other.id_user_sender!=2)
WHERE
-- ensure tm is last message in thread
(tm_next.id_thread is null)and
(
-- there is a non deleted message from another user in current thread
(tm_other.id_thread_messages is not null)or
-- last message is not from current user
(tm.id_user_sender!=2)
)
SqlFiddle is here.
Let me know is this working for you.
i think this is the solution that you are looking for
SELECT * FROM thread
JOIN thread_users ON thread.id_thread = thread_users.id_thread
JOIN thread_messages ON thread.id_thread = thread_messages.id_thread
JOIN message_status ON thread_messages.id_thread_messages = message_status.id_thread_messages
WHERE thread_users.id_user = 2
AND thread_users.id_user = message_status.id_user
AND message_status.status != 0
AND message_status.status != 4
AND thread.id_user_last != message_status.id_user
Now with the description of what INBOX means I suggest you rely heavily on EXISTS clause in your query. Here is just an example of how it can look like:
SELECT *
FROM thread t INNER JOIN
thread_messages tm ON t.id_thread = tm.id_thread
WHERE
EXISTS ( -- User is in the thread.
SELECT * FROM thread_users tu
WHERE t.id_thread = tu.id_thread AND tu.id_user = 2
)
AND NOT EXISTS ( -- Exclude earlier messages for thread.
SELECT * FROM thread_messages WHERE
tm.id_thread = id_thread AND datetime > tm.datetime
AND EXISTS (-- Exclude deleted messages here
SELECT * FROM message_status
WHERE thread_messages.id_thread_messages = id_thread_messages
AND status != 0
AND status != 4
)
)
AND EXISTS ( -- Include messages that were not deleted or send to self.
SELECT * FROM message_status
WHERE tm.id_thread_messages = id_thread_messages
AND status != 0
AND status != 4
AND t.id_user_last != id_user -- not sure what is this for
)
AND EXISTS ( -- Include threads with messages from several users
SELECT * FROM thread_messages
WHERE tm.id_thread = id_thread
AND tm.id_user_sender != t.id_user_inital)
http://sqlfiddle.com/#!2/1c5fc3/39

MySQL UPDATE not updating properly

I've got an UPDATE query as followed:
UPDATE orders
SET
order_status = 1,
amount_remaining = 0.00000000
WHERE
market_pair_id = 2 AND user_id = 1
AND sale_rate = 0.00000001
AND sale_amount = 100.00000000
AND order_type = 1 LIMIT 1
Here's a snapshot of my data from phpmyadmin:
http://cl.ly/image/3m3M2f2R3R3Z/Screen%20Shot%202014-01-20%20at%2012.55.03.png
There's clearly 3 matching rows for my query however none of them are updated with the message 0 rows affected. Can someone shed light on what's going on?
Some added info: I can't update via the primary key because I dont have it, and my goal is simply to update 1 of many matching rows of my data.
Thanks very much in advance
Delete LIMIT 1 from end of your query and try
UPDATE orders
SET
order_status = 1,
amount_remaining = 0.00000000
WHERE
market_pair_id = 2 AND user_id = 1
AND sale_rate = 0.00000001
AND sale_amount = 100.00000000
AND order_type = 1
.try this
UPDATE orders
SET
order_status = 1,
amount_remaining = 0.00000000
WHERE order_id IN (
SELECT order_id FROM (
SELECT order_id FROM orders
WHERE market_pair_id = 2
AND user_id = 1
AND sale_rate = 0.00000001
AND sale_amount = 100.00000000
AND order_type = 1
LIMIT 1
) tmp
);