I'm trying to work out an average between of time between two dates in the same field.
Basically i've got a transaction date and an id for each transaction and a customer id for each transaction.
I need to get the time between the first transaction and the second transaction. I dont mind working out the average between the two in excel but I dont know how to pull two dates from the same field.
transaction.created_at of the first transaction minus transaction.created_at of the second transaction for each and every customer in the database. I can pull the date of a transaction like
select
customer.id,
transaction.created_at
count(transaction.id)
from transaction
having count(transaction.id) = 2
Thanks
Not sure if this will always be Having count(*) = 2? If so, I think you could just use min and max, no?
/*
create table dbo.Example (tran_id int,created_at datetime,cust_id int)
insert dbo.example values (1,'10/1/2012',900)
insert dbo.example values (2,'10/2/2012',901)
insert dbo.example values (3,'10/18/2012',590)
insert dbo.example values (4,'10/10/2012',676)
insert dbo.example values (5,'10/11/2012',123)
insert dbo.example values (6,'10/17/2012',456)
insert dbo.example values (7,'10/9/2012',901)
insert dbo.example values (8,'10/30/2012',900)
insert dbo.example values (9,'10/4/2012',456)
insert dbo.example values (10,'10/17/2012',676)
*/
select
cust_id,
max([created_at]) as [Last Date],
min([created_at]) as [First Date],
datediff(hh,min([created_at]) ,max([created_at])) as [Hours diff]
from example
group by cust_id
having count(*) = 2
order by cust_id
Try the following to retrieve particular customer transactions count:
Select
Customer.id,
count(transaction.id)
from transaction
where Customer.id = '10'
Here 10 specifies the customer id that has been searched by you. You have to pass this customer id as parameter in your created SP.
Related
Say there are three tables for your bakery business:
online_order
invoice
customer_id
Your boss calls you and says "I need to order a chocolate cake for all of our clients, invoice them all separately as well". So now you have to do two things:
Create an online_order entry for each client
Then invoice them for that order.
However, each client needs to have their OWN online_order number that they can reference on their invoice.
How can you do this in one transaction? Below is what I have (psuedocode) but I'll show you my output and expected output.
BEGIN;
-- First lets create the order
INSERT INTO online_order (online_order_id, date, cake_type, cake_flavor)
VALUES
(AUTO_INCREMENT, NOW(), round, chocolate);
-- Then take that online_order_id and create an invoice out of it for one of our customers
INSERT INTO invoice (date, online_order_id, invoice_amt, customer_id)
SELECT
NOW(),
LAST_INSERT_ID(),
10.00,
CUSTOMER_ID
FROM CUSTOMER;
ROLLBACK;
END;
My output
-- Let's say the next auto-incremented online_order_id is 10011:
INSERT INTO invoice VALUES ("2016-01-01", 10011, 10.00, "1");
INSERT INTO invoice VALUES ("2016-01-01", 10011, 10.00, "2");
INSERT INTO invoice VALUES ("2016-01-01", 10011, 10.00, "3");
INSERT INTO invoice VALUES ("2016-01-01", 10011, 10.00, "4");
INSERT INTO invoice VALUES ("2016-01-01", 10011, 10.00, "5");
Desired output (different online_order_id for each invoice)
INSERT INTO invoice VALUES ("2016-01-01", 10011, 10.00, "1");
INSERT INTO invoice VALUES ("2016-01-01", 10012, 10.00, "2");
INSERT INTO invoice VALUES ("2016-01-01", 10013, 10.00, "3");
INSERT INTO invoice VALUES ("2016-01-01", 10014, 10.00, "4");
INSERT INTO invoice VALUES ("2016-01-01", 10015, 10.00, "5");
I need to insert an order, then insert an invoice, then insert an order, then insert an invoice.... for each client. How can I write this in MySQL? Thank you!
You can create a table to maintain the IDs for different entity and use SELECT.. FOR UPDATE to get the atomic values. Table would look like this:
Entity | Value
Order | 1
Blah | 2
You can then use the following block to get the new id:
set #id := select value from Ids where Entity = 'Order' FOR UPDATE;
update Ids set value = value + 1 Enity = 'Order';
commit;
This would give you the id and increment it by 1. This id then can be used in invoide table.
As you will be using select.. for update, corresponding row will be locked and no other transaction will be able to read/modify the value, resulting in atomicity.
This approach might prove to be a bottleneck if you have too many insertions executing in parallel.
Your pseudocode doesn't make much sense - you should only rollback the transaction if it fails. But leaving that aside for now, inserting one row at a time is very innefficient. I would go with something like....
INSERT INTO invoice
(date, online_order_id, invoice_amt, customer_id, reference)
SELECT
NOW(), LAST_INSERT_ID(), 10.00, CUSTOMER_ID, CONNECTION_ID()
FROM CUSTOMER;
INSERT INTO online_order
(date, cake_type, cake_flavor)
SELECT NOW(), 'round', 'chocolate'
FROM invoice
WHERE reference=CONNECTION_ID();
UPDATE invoice SET reference=NULL
WHERE reference=CONNECTION_ID();
The above ensures most of the consistency without the use of a transaction at all, although with a procedure you could create a variable and assign its value from uuid() those obviating the need for the final update and keeping an index on reference well balanced.
I have two tables, a booking table and an invoice table. I am trying to update the booking table with booking information and get a max value from the invoice table and insert it into the booking table at the same time.
So far I have this, but it doesn't set any values to the Booking.Invoice_id column
INSERT INTO Booking( user_id, Location_id, Accom_Id,StartDate,EndDate,
Vehreg,PartySize,Invoice_id )
VALUES ('$User_id', '$pitch', '$Accom' , '$start',
'$end','$Vreg','$guests','SELECT Max Invoice_id FROM Invoice;');
any help would be much appreciated
Use insert . . . select:
INSERT INTO Booking(user_id, Location_id, Accom_Id, StartDate, EndDate,
Vehreg, PartySize, Invoice_id )
SELECT '$User_id', '$pitch', '$Accom' , '$start',
'$end', '$Vreg', ' $guests',
MAX(Invoice_ID)
FROM Invoice;
My guess, however, is that you want to run this immediately after inserting a row into Invoice. In that case, you should be using LAST_INSERT_ID().
How do I preserve the last_insert_id() into a specific record?
Here are my queries:
INSERT INTO student(student_name) VALUES ('ramgopal')`;
SELECT `last_insert_id()`;
INSERT INTO grades (student_id,grade) VALUES (last_insert_id(),'A');
INSERT INTO class (semester,day,time) VALUES ('spring 2015','tuesday','12');
SELECT last_insert_id();
insert INTO grades(class_id) VALUES (last_insert_id());
In grade table I got grade_id, class_id, student_id and grade records.
When I use the last_insert_id() again it is just inserting the latest id and the previous id is not inserting. So I would like to preserve the initial last_insert_id for further use.
I have two variables
1. inserted_user_id,
2. inserted_address_id
in my MySQL procedure.
I need to use them in insert queries and select queries. Im trying something like
insert into user_new(name, company, email, customer_id) select name,
company, email, inserted_user_id from user_old;
insert into user_address_map(address_id, user_id) select
inserted_user_id,inserted_address_id ;
There two statements are not working. How to use procedure variable's value in the above sql statements?
First make a select to get all the info: (you need to declare these variables first)
SELECT name,
company,
email,
INTO varname, varcompany, varemail
FROM user_old
then use it into insert
INSERT INTO user_new
(name,
company,
email,
customer_id)
VALUES (varname,
varcompany,
varemail,
inserted_user_id);
edit:
First insert the Selected values and get the id of the inserted row
INSERT INTO user_new
(name,
company,
email)
SELECT name,
company,
email
FROM user_old
SET out_param = last_insert_id();
Then update this row with your param
UPDATE user_new
SET customer_id = inserted_user_id
WHERE id = out_param;
This question already has answers here:
Check if a row exists, otherwise insert
(12 answers)
MySQL Conditional Insert
(13 answers)
Closed 9 years ago.
I want to run a set of queries to insert some data into an SQL table but only if the record satisfying certain criteria are met. The table has 4 fields: id (primary), fund_id, date and price
I have 3 fields in the query: fund_id, date and price.
So my query would go something like this:
INSERT INTO funds (fund_id, date, price)
VALUES (23, '2013-02-12', 22.43)
WHERE NOT EXISTS (
SELECT *
FROM funds
WHERE fund_id = 23
AND date = '2013-02-12'
);
So I only want to insert the data if a record matching the fund_id and date does not already exist. If the above is correct it strikes me as quite an inefficient way of achieving this as an additional select statement must be run each time.
Is there a better way of achieving the above?
Edit: For clarification neither fund_id nor date are unique fields; records sharing the same fund_id or date will exist but no record should have both the same fund_id and date as another.
This might be a simple solution to achieve this:
INSERT INTO funds (ID, date, price)
SELECT 23, DATE('2013-02-12'), 22.5
FROM dual
WHERE NOT EXISTS (SELECT 1
FROM funds
WHERE ID = 23
AND date = DATE('2013-02-12'));
p.s. alternatively (if ID a primary key):
INSERT INTO funds (ID, date, price)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE ID = 23; -- or whatever you need
see this Fiddle.
Although the answer I originally marked as chosen is correct and achieves what I asked there is a better way of doing this (which others acknowledged but didn't go into). A composite unique index should be created on the table consisting of fund_id and date.
ALTER TABLE funds ADD UNIQUE KEY `fund_date` (`fund_id`, `date`);
Then when inserting a record add the condition when a conflict is encountered:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = `price`; --this keeps the price what it was (no change to the table) or:
INSERT INTO funds (`fund_id`, `date`, `price`)
VALUES (23, DATE('2013-02-12'), 22.5)
ON DUPLICATE KEY UPDATE `price` = 22.5; --this updates the price to the new value
This will provide much better performance to a sub-query and the structure of the table is superior. It comes with the caveat that you can't have NULL values in your unique key columns as they are still treated as values by MySQL.
Assuming you cannot modify DDL (to create a unique constraint) or are limited to only being able to write DML then check for a null on filtered result of your values against the whole table
FIDDLE
insert into funds (ID, date, price)
select
T.*
from
(select 23 ID, '2013-02-12' date, 22.43 price) T
left join
funds on funds.ID = T.ID and funds.date = T.date
where
funds.ID is null