MySql Copy a row, amend value and insert each row - mysql

I have a table with 7 fields - one, product_special_id, being AUTO_INCREMENT.
The table contains the product prices for different product groups.
So for example:
product_special_id: 1532 (AUTO_INCREMENT)
product_id: 4
customer_group_id: 3
priority: 0
price: 280.5000
date_start: 0000-00-00
date_end: 0000-00-00
I need to copy each record assigned to customer_group_id '3' to a new record in the same table with a new customer_group_id - lets say '5'.
The product_special_id for the new record must be unique. The remaining five fields remain the same.
The original record needs remain unaltered.
Can this be done?
Thanks

Just use insert . . . select:
insert into t(product_id, customer_group_id, priority, price, date_start, date_end)
select product_id, 5, priority, price, date_start, date_end
from t
where customer_group_id = 3;

This query work for your issue:
insert into `tablename` (product_id,customer_group_id,priority,price,date_start,date_end)
select product_id,5,priority,price,date_start,date_end from `tablename` where customer_group_id=3
For more information about insert select syntax see the mysql documentation.

Related

I attended a Hackerrank online test and I got this question, I couldn't solve it, Help me out if you can

Question's Image
I am not able to understand how to show the details for the same person for different dates, what do I group the data by for this to happen?
I have added an Image of the question do check the link out on top, it won't let me post embedded images as I am new to stackoverflow.
I have made a sample test case tables for the problem for your convinence.
Please help out if you can.
Create Table delivery
(
deliveryId int primary key,
delivery_date date,
De_Id int ,
Pickup_time time ,
delivery_time time
);
Insert Into delivery Values (450, '2020-04-17' , 111, '8:00', '9:00');
Insert Into delivery Values (451, '2020-04-17' , 111, '21:00', '23:00');
Insert Into delivery Values (452, '2020-04-17' , 111, '11:00', '11:30');
Insert Into delivery Values (453, '2020-04-17' , 112, '2:00', '3:35');
Insert Into delivery Values (454, '2020-04-17' , 112, '4:00', '4:40');
Insert Into delivery Values (455, '2020-04-17' , 112, '5:00', '7:00');
Insert Into delivery Values (456, '2020-04-18' , 111, '9:00', '11:00');
Insert Into delivery Values (457, '2020-04-18' , 111, '8:50', '9:55');
Insert Into delivery Values (458, '2020-04-18' , 111, '7:00', '9:06');
Insert Into delivery Values (459, '2020-04-18' , 112, '2:00', '3:35');
Insert Into delivery Values (460, '2020-04-18' , 112, '4:00', '4:40');
Insert Into delivery Values (461, '2020-04-18' , 112, '5:00', '7:00');
Create Table delivery_executive
(
ID int primary key,
Name varchar(20)
);
Insert into delivery_executive Values (111, 'Abby');
Insert into delivery_executive Values (112, 'Binto');
Here's one way to solve using MySql using row_number to order each delivery by the difference between the times, then filtering out all except the highest two, then using a conditional aggregate to pivot both rows with columns for each Id
with t as (
select deliveryid, de_id, delivery_date,
Row_Number() over(partition by delivery_date, de_id order by subtime(delivery_time,Pickup_time) desc)rn
from delivery
)
select e.Name, t.delivery_date,
Max(case when rn=1 then t.deliveryid end) FirstDeliveryId, Max(case when rn=2 then t.deliveryid end) SecondDeliveryId
from t
join delivery_executive e on e.id=t.de_id
where rn<=2
group by t.delivery_date, e.Name
How max and case help.
It helps to work through in stages. So firstly if we start with just what the CTE (the with t as ) element returns for the sample data, we see 12 rows - 6 for each date - each with 3 rows per de_id and a row number rn ordered 1-3 against each group with 1 having the longest time between the pickup and delivery times and 3 the shortest.
If we just look at select * from t where rn<=2, that naturally removes the the rows where rn=3 and we're left with the data we want, the two longest delivery time periods for each date, for each executive.
The desired output is to have just two rows per each executive, one for each date, and the two IDs to be in two columns.
Looking at case first, we can add two new columns as the result of a case expression,
case when rn=1 then t.deliveryId end,
case when rn=2 then t.deliveryId end
The first case will have a value only where rn=1 likewise the second case will have a value only where rn=2 (by default without an else it returns NULL on all other non-matched cases).
So now we have our First and Second Id values but they are still split over two rows.
The other values on each pair of rows (rn=1 and rn=2), are the same in each case, being the same delivery_date and the same de_id, so this is now where we can aggregate the rows together.
The final selected columns are the de_id and delivery_date and we want to group by these - ie all the values that are the same are condensed onto a single row provided the columns that we do not group by are aggregated in some way.
The most common aggregation would be sum, for example if we were only selecting the row number column we could sum(rn) and the result would be 3 for each aggregated group (1+2). However using max it will return the maximum value for each group of rows, and since we only have either a value (deliveryId) or NULL, it returns the deliveryId.
Therefore we wrap each case expression with a max() function, group by the remaining columns and the result is the grouped columns occupy a single row in each case since the aggregate of the case expressions also returns 1 row.
Fiddle here

Insert data in mysql table if sum of a column is greater or equal to specific integer

I am trying to Run this Query
INSERT INTO point(description, username, _by, date_time, p)
VALUES ('Test By System','username','System',now(),if( (SELECT SUM(p) FROM point WHERE username = 'username') - 1 >=0 , - 1 ,0));
The thing i am really trying to achieve is if SUM of a column is greater or equal to 1 2 or 3 then insert a new Row in the Table.

How to update and insert into db with #transactional on db query

I have one table warehouse_item_mapping
having columns - warehouseId, itemId, stockQuantity
warehouse_id item_id stock_quantity
1 123 10
1 234 20
1 345 30
This table is being used as inventory management as maintaining current stock of items in warehouse.
Now if new stock has come with some items including new items with current stock quantity.
Like
1 123 50
1 234 50
1 678 50 (new item)
I have to update the stock quantity in table as sum of existing quantity and current stock quantity. And if mapping not found in table then insert that new mapping.
For this case table should be updated as
warehouse_id item_id stock_quantity
1 123 60
1 234 70
1 345 30
1 678 50
How to do this in single query.
Follow up question in this is
If someone used the current stock from table in between get and update query then how to maintain lock or transactional for whole flow.
INSERT ON DUPLICATE KEY UPDATE is what you need. In combination with pre selected stock_quantity. You need to make item_id PRIMARY KEY.
Now of course you will be using one SELECT and one INSERT INTO statement with PHP ( i guess) variables.
SELECT #stock_quantity:=stock_quantity FROM warehouse_item_mapping WHERE item_id=123;
INSERT INTO warehouse_item_mapping (warehouse_id, item_id, stock_quantity)
VALUES (1, 123, 50)
ON DUPLICATE KEY UPDATE warehouse_id=1, stock_quantity=#stock_quantity+50;
Working example: db-fiddle
RESULT:
Results
Query #1 Execution time: 0ms
warehouse_id item_id stock_quantity
1 123 60
1 234 70
1 345 30
1 678 50
SO lats say you are using PHP:
PHP:
'$item_id' // your new OR old inserting item id.
'$warehouse_id'
'$stock_quantity' // Your NEW stock number.
START TRANSACTION;
SELECT #stock_quantity:=stock_quantity
FROM warehouse_item_mapping WHERE item_id='$item_id';
INSERT INTO warehouse_item_mapping (warehouse_id, item_id, stock_quantity)
VALUES ('$warehouse_id', '$item_id', '$stock_quantity')
ON DUPLICATE KEY UPDATE warehouse_id='$warehouse_id', stock_quantity=#stock_quantity+'$stock_quantity';
COMMIT;
This will try to insert a value only if PRIMARY KEY item-id doesn't exists. If it does it will update other two fields.
EDIT:
I think you are confused what #transaction is, read about it here.
Above is example of one as you asked for it but this can also be done in one query as mentioned in comment. Example:
INSERT INTO warehouse_item_mapping (warehouse_id, item_id, stock_quantity)
VALUES (1, 123, 50) ON DUPLICATE KEY UPDATE
warehouse_id=1, stock_quantity=stock_quantity+50;
Working Fiddle.
PHP:
INSERT INTO warehouse_item_mapping (warehouse_id, item_id, stock_quantity)
VALUES ('$warehouse_id', '$item_id', '$stock_quantity') ON DUPLICATE KEY
UPDATE warehouse_id='$warehouse_id', stock_quantity=stock_quantity+'$stock_quantity';

How to select row with same id and add its field value

I have table medicine record with fields
Name qunty min expiry
a 2 3 14/2/2012
b 4 1 15/12/2010
a 5 3 16/5/2012
I have to select medicine which has qunty less than min value . Two rows can exist with same name but with different expiry . So in that condition i have to add qunty of same name row and than match with min value .
try this one,
SELECT Name, `min`, SUM(qunty) totalQunty
FROM medicine
GROUP BY NAME, `min`
HAVING SUM(qunty) < `min`
SQLFiddle Demo
in that case i have also a question with you, are min values constant for the same name?

Creating a frequency table in Access VBA

I have a table where different participants are given multiple boxes of medicines on multiple days. I am trying to create a frequency table showing how much medicines have been distributed by the number of boxes to the participants.
The result I'm looking for is -
2 boxes = 1 (since only Lynda got a total of 2 boxes), 4 boxes = 2 (since Ryan and Rinky both got a total of 4 boxes after adding up the medicine boxes)
Please let me know what approach would be the best in this case.
Thanks for your help.
-Nams
I think you want:
SELECT t.SumOf, Count(t.[PARTICIPANT ID]) AS CountOf
FROM (SELECT Table1.[PARTICIPANT ID], Sum(Table1.MEDICINE_BOX) AS SumOf
FROM Table1
GROUP BY Table1.[PARTICIPANT ID]) AS t
GROUP BY t.SumOf;
Where table1 is the name of your table.
If your table is like this:
medicine_dispense
participantID date amount_boxes
ABC 8/29/12 1
ABC 8/30/12 2
XYZ 8/29/12 1
XYZ 8/30/12 1
then a query like this:
select
amount_boxes, count(participantID)
from
medicine_dispense
should work
I'll use generic SQL. You can paste SQL into Access queries in SQL view. (You might have to delete the CHECK() constraint.)
create table participant_meds (
participant varchar(10) not null,
distribution_date date not null default current_date,
num_boxes integer not null check (num_boxes > 0),
primary key (participant, distribution_date)
);
insert into participant_meds values ('Ryan', '2012-02-03', 1);
insert into participant_meds values ('Ryan', '2012-06-07', 3);
insert into participant_meds values ('Rinky', '2012-02-28', 4);
insert into participant_meds values ('Lynda', '2012-03-04', 2);
insert into participant_meds values ('Russ', '2012-04-05', 2);
insert into participant_meds values ('Russ', '2012-05-08', 2);
insert into participant_meds values ('Russ', '2012-06-12', 2);
Resulting data, sorted, for copy/paste.
participant distribution_date num_boxes
Lynda 2012-03-04 2
Rinky 2012-02-28 4
Russ 2012-04-05 2
Russ 2012-05-08 2
Russ 2012-06-12 2
Ryan 2012-02-03 1
Ryan 2012-06-07 3
This query gives you the total boxes per participant.
select sum(num_boxes) boxes, participant
from participant_meds
group by participant;
6;"Russ"
2;"Lynda"
4;"Ryan"
4;"Rinky"
Use that query in the FROM clause as if it were a table. (I'd consider storing that query as a view, because I suspect that the total number of boxes per participant might be useful. Also, Access has historically been good at optimizing queries that use views.)
select boxes num_boxes, count(participant) num_participants
from (select sum(num_boxes) boxes, participant
from participant_meds
group by participant) total_boxes
group by num_boxes
order by num_boxes;
num_boxes num_participants
--
2 1
4 2
6 1