Insert INTO MySQL FROM another table - mysql

INSERT INTO campaign_ledger (`campaign_id`, `description`, amount, balance, timestamp)
VALUES (SELECT id as campaign_id, 'Ported from campaigns' as description, budget_remaining as amount, budget_remaining as balance, NOW() as timestamp FROM campaigns)
That's my syntax, but I get an error saying:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near 'SELECT id as campaign_id, 'Ported from campaigns' as
description, budget_remaini' at line 2
What am I doing wrong?

Since you are selecting from a table then you will want to use an INSERT INTO SELECT FROM query:
INSERT INTO campaign_ledger
(
`campaign_id`
, `description`
, amount
, balance
, timestamp
)
SELECT
id as campaign_id
, 'Ported from campaigns' as description
, budget_remaining as amount
, budget_remaining as balance
, NOW() as timestamp
FROM campaigns
Only use INSERT INTO VALUES when you are using specific values and not selecting from a table. If you wanted to use INSERT INTO VALUES then your query would be like this:
INSERT INTO campaign_ledger
(
`campaign_id`
, `description`
, amount
, balance
, timestamp
)
VALUES
(
1
, 'test'
, 100.00
, 1000.00
, NOW()
)

INSERT INTO campaign_ledger (`campaign_id`, `description`, amount, balance, timestamp)
SELECT id as campaign_id, 'Ported from campaigns' as description,
budget_remaining as amount,budget_remaining as balance,
NOW() as timestamp FROM campaigns;

The VALUES part of the query is not necessary. For example:
INSERT INTO campaign_ledger (`campaign_id`, `description`, amount, balance, timestamp)
SELECT id as campaign_id, 'Ported from campaigns' as description,
budget_remaining as amount, budget_remaining as balance,
NOW() as timestamp
FROM campaigns;

Related

MySQL Selecting wrong column value in Group By query with alias in where clause

I know this question was already asked in a similar way, but I could not found any with an alias in the where clause.
I have a table structure like this:
CREATE TABLE Orders
( ID int NOT NULL Primary Key
, OrderNr VARCHAR(6) NOT NULL
, Date DATE NOT NULL
, Time CHAR(6) NOT NULL
, GeoCode CHAR(6) NULL) ;
My insert looks like this:
INSERT INTO orders (ID, OrderNr, Date, Time, GeoCode) VALUES (1, '123456', '2022-02-
15', '111110', '4022')
, (2, '123457', '2022-02-15', '121210', '4022')
, (3, '123455', '2021-04-15', '171515', '4020')
, (4, '123455', '2021-04-16', '150302', '4022')
, (5, '123466', '2022-03-03', '191810', '4020')
, (6, '123466', '2022-03-04', '121410', '4022')
Now I´m trying to get the latest Date and Time values for all OrderNr like this:
SELECT ID, OrderNr, MAX(cast(concat(Date, ' ', cast(Time as Time)) as datetime)) as
DateAndTime, GeoCode
FROM Orders o1
GROUP BY OrderNr
The Results shows the right latest date and time but the GeoCode is wrong. E.g for the
OrderNr 123455 it is 4020 but should be 4022.
I know that similar question were already asked but I cant use the alias in the where clause. Can somebody explain to me what I´m doing wrong?
Thank you very much in advance.
If your mysql version support ROW_NUMBER window function you can try this
SELECT *
FROM (
SELECT ID,
OrderNr,
cast(concat(Date, ' ', cast(Time as Time)) as datetime) DateAndTime,
GeoCode,
ROW_NUMBER() OVER(PARTITION BY OrderNr ORDER BY cast(concat(Date, ' ', cast(Time as Time)) as datetime) DESC) rn
FROM Orders o1
) t1
WHERE rn = 1
or use subquery with EXISTS
SELECT *
FROM Orders o1
WHERE EXISTS (
SELECT 1
FROM Orders oo
WHERE oo.OrderNr = o1.OrderNr
HAVING MAX(oo.Date) = o1.Date
)
sqlfiddle

How to get percentage of result set for each day?

I am trying to retrieve the percentage of available products at specific merchants over the last 30 days.
Desired result example:
20210504 merchant1 20%
20210504 merchant2 30%
20210505 merchant1 25%
20210505 merchant2 35%
There are 3 tables:
availability (containing availability info for each product and merchant and day)
products (where the manufacturer_id is, that we want to filter for)
merchants (merchant info)
Minimal example: https://www.db-fiddle.com/f/wtnK5R4DWi7Dy6LwLaP4mX/0
This returns the percentage for only one merchant and one day:
-- get percentage of available products per merchant over time
SELECT
m.name AS metric,
t.s AS AMOUNT_AVAILABLE,
count(*) AS AMOUNT_TOTAL,
t.s / count(*) AS percentage
FROM availability p
CROSS JOIN (
SELECT count(*) AS s FROM availability p2
INNER JOIN products mp on p2.SKU = mp.SKU
WHERE
availability = 'sofort lieferbar'
AND date = curdate() - interval 1 day -- testing for one day, but we want a time series
AND mp.MANUFACTURER_ID = 1
-- AND p2.merchant_id = p.merchant_id -- does not work
-- AND merchant_id = 2
-- GROUP BY merchant_id
) t
INNER JOIN products mp on p.SKU = mp.SKU
INNER JOIN merchants m ON m.id = p.MERCHANT_ID
WHERE
p.date = curdate() - interval 1 day
and mp.MANUFACTURER_ID = 1
-- and merchant_id = 2
GROUP BY
merchant_id
Now I am trying to somehow merge the cross join with the from table so I get the info for each merchant and day. How can a cross join be joined with the from table?
Data & Shema:
create table merchants
(
id tinyint unsigned not null
primary key,
name varchar(255) null
);
INSERT INTO merchants (id, name) VALUES (1, 'Amazon');
INSERT INTO merchants (id, name) VALUES (2, 'eBay');
create table availability
(
DATE date not null,
SKU char(10) not null,
merchant_id tinyint unsigned not null,
availability enum ('sofort lieferbar', 'verzögert lieferbar', 'nicht lieferbar', 'außer Handel') null,
constraint DATE
unique (DATE, SKU, merchant_id)
);
INSERT INTO test.availability (DATE, SKU, merchant_id, availability) VALUES ('2021-05-11', '1', 1, 'sofort lieferbar');
INSERT INTO test.availability (DATE, SKU, merchant_id, availability) VALUES ('2021-05-11', '1', 2, 'nicht lieferbar');
INSERT INTO test.availability (DATE, SKU, merchant_id, availability) VALUES ('2021-05-12', '1', 1, 'sofort lieferbar');
INSERT INTO test.availability (DATE, SKU, merchant_id, availability) VALUES ('2021-05-12', '1', 2, 'nicht lieferbar');
INSERT INTO test.availability (DATE, SKU, merchant_id, availability) VALUES ('2021-05-13', '1', 1, 'nicht lieferbar');
INSERT INTO test.availability (DATE, SKU, merchant_id, availability) VALUES ('2021-05-13', '1', 2, 'sofort lieferbar');
create table products
(
SKU char(8) not null
primary key,
NAME varchar(255) null,
MANUFACTURER_ID mediumint unsigned null,
updated datetime default CURRENT_TIMESTAMP not null on update CURRENT_TIMESTAMP
);
INSERT INTO test.products (SKU, NAME, MANUFACTURER_ID, updated) VALUES ('1', 'Sneaker', 1, '2021-05-12 02:27:46');
INSERT INTO test.products (SKU, NAME, MANUFACTURER_ID, updated) VALUES ('2', 'Ball', 1, '2021-05-12 02:27:46');
INSERT INTO test.products (SKU, NAME, MANUFACTURER_ID, updated) VALUES ('3', 'Pen', 2, '2021-05-12 02:27:46');
INSERT INTO test.products (SKU, NAME, MANUFACTURER_ID, updated) VALUES ('4', 'Paper', 2, '2021-05-12 02:27:46');
I have written a query which seems to work for the data you have provided. Let me know if there's any issue and I'll see what I can do.
SELECT CONCAT('merchant', t.ID) as merchant,
t.Date,
g.prod_available / t.all_prod_from_merch AS percentage_available
# gets total number of products in time range Date,
FROM (SELECT ID,
COUNT(merchant_ID) AS all_prod_from_merch
FROM merchants m
JOIN availability a
ON m.ID = a.merchant_ID
WHERE Date < CURDATE()
AND Date >= curdate() - INTERVAL 10 DAY
GROUP BY merchant_ID,
Date ) t
LEFT JOIN (SELECT merchant_ID,
Date,
COUNT(merchant_ID) AS prod_available
FROM availability
WHERE AVAILABILITY = 'sofort lieferbar'
AND date IN (SELECT Date
FROM availability
WHERE date < CURDATE()
AND date >= CURDATE() - INTERVAL 10 DAY
GROUP BY Date )
GROUP BY merchant_ID,
Date ) g
ON g.merchant_ID = t.ID
AND g.Date = t.Date
ORDER BY t.date;
The first select in the join gets the total number of products in the time range for each merchant. The second one gets those available from each merchant. So the select at the beginning just does the fraction.

How to find cumulative sum between two dates in MySQL?

How to find cumulative sum between two dates taking into account the previous state?
Putting WHERE condition
WHERE date BETWEEN '2021-02-19 12:00:00'AND '2021-02-21 12:00:00';
doesn't do the job because the sum starts from the first condition's date, and not from the first record. I would like to select only part of the whole query (between two dates), but to calculate cumulative sum from the first (initial) state.
I prepared Fiddle
CREATE TABLE `table1` (
`id` int(11) NOT NULL,
`date` datetime NOT NULL DEFAULT current_timestamp(),
`payment` double NOT NULL
);
INSERT INTO `table1` (`id`, `date`, `payment`) VALUES
(1, '2021-02-16 12:00:00', 100),
(2, '2021-02-17 12:00:00', 200),
(3, '2021-02-18 12:00:00', 300),
(4, '2021-02-19 12:00:00', 400),
(5, '2021-02-20 12:00:00', 500),
(6, '2021-02-21 12:00:00', 600),
(7, '2021-02-22 12:00:00', 700);
version();
SELECT DATE_FORMAT(date, "%Y-%m-%d") AS date,
payment, SUM(payment) OVER(ORDER BY id) AS balance
FROM table1
WHERE date BETWEEN '2021-02-19 12:00:00'AND '2021-02-21 12:00:00';
You must filter the table after you get the cumulative sums:
SELECT *
FROM (
SELECT DATE(date) AS date,
payment,
SUM(payment) OVER(ORDER BY id) AS balance
FROM table1
) t
WHERE date BETWEEN '2021-02-19'AND '2021-02-21';
or:
SELECT *
FROM (
SELECT DATE(date) AS date,
payment,
SUM(payment) OVER(ORDER BY id) AS balance
FROM table1
WHERE DATE(date) <= '2021-02-21'
) t
WHERE date >= '2021-02-19';
See the demo.
Results:
date
payment
balance
2021-02-19
400
1000
2021-02-20
500
1500
2021-02-21
600
2100

MYSQL INSERT INTO WITH SELECT not working?

i am trying to do a insert into a with SELECT, bit this following query doesnt seems to be working for some reason,
INSERT INTO `employer_data`
(`employer_id`, `data`, `datetime`)
VALUES
( SELECT employer_id, employer_id AS data, NOW() AS `datetime` FROM employer );
Any ideas ?
remove values keyword
INSERT INTO `employer_data`
(`employer_id`, `data`, `datetime`)
( SELECT employer_id, employer_id AS data, NOW() AS `datetime` FROM employer );
Syntax was wrong.
Try:
INSERT INTO `employer_data`
(`employer_id`, `data`, `datetime`)
SELECT employer_id, employer_id AS data, NOW() AS `datetime` FROM employer;
Refer To:
MySQL: INSERT ... SELECT Syntax

How to combine sql request with data in another table

I have two tables, first "users_counts"
id int(11) AUTO_INCREMENT
name varchar(250)
And I have second table "counts_data"
id int(11) AUTO_INCREMENT
id_user int(11)
count int(11)
date datetime
I want to select all records from the first table and get some data from a second, and then I want to merge they. I want create temp (for one request) column where collect last count with order by date in second table and second column where collect collect penultimate count with order by date in second table.
INSERT INTO `users_counts` (`id`,`name`) VALUES ('1','John');
INSERT INTO `users_counts` (`id`,`name`) VALUES ('2','Michael');
INSERT INTO `users_counts` (`id`,`name`) VALUES ('3','Den');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('1','1', '200', '2012.09.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('2','1', '212', '2012.09.01');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('3','2', '20', '2012.01.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('4','3', '210', '2012.02.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('5','3', '2033', '2012.03.09');
INSERT INTO `counts_data` (`id`,`id_user`, `count`, `date`) VALUES ('6','3', '1', '2012.04.09');
In the end, after a request I want to get something like this
id name count count_before
1 John 200 212
2 Michael 20 0
3 Den 1 2033
Thank.
Another possible way to do this:
select uc.id,
uc.name,
(select count
from counts_data cd
where cd.id_user = uc.id
order by date desc limit 1) as count,
ifnull((select count
from counts_data cd
where cd.id_user = uc.id
order by date desc limit 1 offset 1),0) as count_before
from users_counts uc;
Since you only need one value from the counts_data for each row/record, you can use in-line queries in mySQL
SQL Fiddle
select uc.id
, uc.name
, cd1.count
, cd3.count as count_before
from users_counts uc
left join
counts_data cd1
on cd1.id_user = uc.id
and cd.date =
(
select max(date)
from counts_data cd2
where cd2.id_user = uc.id_user
)
left join
counts_data cd3
on cd3.id_user = uc.id
and cd.date =
(
select max(date)
from counts_data cd4
where cd4.id_user = uc.id_user
and cd4.date <> cd1.date
)