Orders repeat based on condition in SQL Server - sql-server-2008

Based on data need to increase records 2.5 times of existing orders (any orders of that date) based on date wise and id should be unique when increase orders. We can prefix any number starting on id values.
Table : emp
CREATE TABLE [dbo].[emp]
(
[id] [int] NULL,
[name] [varchar](50) NULL,
[sal] [int] NULL,
[dos] [date] NULL
)
GO
INSERT [dbo].[emp] ([id], [name], [sal], [dos])
VALUES (1, N'balu', 10, CAST(N'2016-02-01' AS Date))
INSERT [dbo].[emp] ([id], [name], [sal], [dos])
VALUES (2, N'ravi', 12, CAST(N'2016-02-01' AS Date))
INSERT [dbo].[emp] ([id], [name], [sal], [dos])
VALUES (3, N'hari', 20, CAST(N'2016-03-07' AS Date))
Example: date is 2016-02-01 have 2 records need to increase records 2.5 timesof that is 2 * 2.5 = 5
Final this 2016-02-01 date need to get 5 records for that date similar to other dates
If we take another date is 2016-03-07 this date is have only one record here 1 * 2.5 =2.5. here we can consider 3 records instead of 2.5 count we can round of the value.
Final this date 2016-03-07 need to show 3 records
Final I need to output like below (I have given id, name, sal, dos values sample, we can given values based on date wise and increase 2.5 times of existing order)
id |name |sal |dos
1 |balu |10 |2016-02-01
2 |ravi |12 |2016-02-01
11 |balu |10 |2016-02-01
22 |ravi |12 |2016-02-01
31 |balu |10 |2016-02-01
3 |hari |20 |2016-03-07
23 |hari |20 |2016-03-07
33 |op |10 |2016-03-07
I have tried like emp table records inserted into another tempemp table and tempemp related ids values updates if 1 is there then updated 11
Similar to 2 and need one more records and again I have used another tempemp1 table (temptable) and insert emp record one on that data and updated that records
again that record loaded in to emp table. Final I got 5 records on 2016-02-01 and similar to another date.
Here I can do for two dates. but this logic is not working when I have more than 100k records with different dates and very difficult to do manually date by date
How to write a query to achieve this task in SQL Server?

Related

MySQL - Find start and end of blocks of consecutive rows with the same value

I need to extract and migrate values from one table to another. the source table contains sumarized values for a specific effectivity date. If a value is changed, a new line is written if something is changed on the component values with the data valid starting at this effective date.
source_id
entity_id
effective_date
component_1
component_2
component_3
int(ai)
int
date
int
int
int
1
159
2020-01-01
100
0
90
2
159
2020-05-01
140
50
90
3
159
2020-08-01
0
30
90
5
159
2020-12-01
0
30
50
i need now migrate this data to a new table like this. the goal is that selecting data for a given month the result is the valid data for this month is given.
id
source_id
entity_id
startdate
enddate
component_type
value
int(ai)
int
int
date
date
int
int
each row represents a value for a component valid for a period of month.
I now run the insert update for each effective month by setting it as a parameter.
I insert value changes as new rows to the table an prevent duplicates by using a unique key (entity_id,effective_date,component_type)
SET #effective_date = '2020-01-01';
INSERT INTO component_final
select NULL,
source_id,
entity_id,
effective_date,
NULL,
1,
component_1
FROM component_source
WHERE effective_date = #effective_date
AND component_1>0;
after migrating the first row it should be that result
id
source_id
entity_id
startdate
enddate
component_type
value
1
1
159
2020-01-01
NULL
1
100
2
1
159
2020-01-01
NULL
3
90
SET #effective_date = '2020-05-01';
INSERT INTO component_final
select NULL,
source_id,
entity_id,
effective_date,
NULL,
1,
component_1
FROM component_source
WHERE effective_date = #effective_date
AND component_1>0;
after migrating the second row it should be that result
id
source_id
entity_id
startdate
enddate
component_type
value
1
1
159
2020-01-01
2020-04-30
1
100
2
1
159
2020-01-01
NULL
3
90
3
2
159
2020-05-01
NULL
1
140
4
2
159
2020-05-01
NULL
2
50
so if there is a value change in the future an end date has to be set.
I'm not able to do the second step, updating the data, if the component is changed in the future.
Maybe it is possible to have it as triggers after insert new row with same entity and component - but I was not able to make it work.
Some ideas? I want to handle this only inside of the MySQL.
You do not need the column enddate in the table component_final, because it's value depends on other values in the same table:
SELECT
id,
source_id,
entity_id,
startdate,
( SELECT DATE_ADD(MIN(cf2.startdate),INTERVAL -1 DAY)
FROM component_final cf2
WHERE cf2.startdate > cf1.startdate
AND cf2.source_id = cf1.source_id
AND cf2.entity_id = cf1.entity_id
) as enddate,
component_type,
value
FROM component_final cf1;
I understand that the core issue is how to find the source_ids where a component changes (0 means a removal, so we don't want these entries in the result) and how to assign the respective end dates at the same time. For the sake of illustration I simplify your example a bit:
There is only one component_type (I take into account that there might then be consecutive entries with unchanged value)
there is only one entity_id, so we can ignore it
It should be easy to extend this simpler version to your real-world problem.
To this is an example input:
source_id
effective_date
value
1
2020-01-01
100
2
2020-01-03
100
3
2020-01-05
80
4
2020-01-10
0
5
2020-01-12
30
I would expect the following output to be generated:
source_id
start_date
end_date
value
1
2020-01-01
2020-01-04
100
3
2020-01-05
2020-01-09
80
5
2020-01-12
NULL
30
You can achieve this with one query by joing each row with the previous one to check if the value has changed (find the start dates of periods) and the first row that is in the future and has a different value (find the start of the next period). If there is no previous row, it is considered a start as well. If there is no later update of the value, we have no end_date.
SELECT
main.source_id,
main.effective_date as start_date,
DATE_SUB(next_start.effective_date, INTERVAL 1 DAY) as end_date,
main.value
FROM source main
LEFT JOIN source prev ON prev.effective_date = (
SELECT MAX(effective_date)
FROM source
WHERE effective_date < main.effective_date
)
LEFT JOIN source next_start ON next_start.effective_date = (
SELECT MIN(effective_date)
FROM source
WHERE effective_date > main.effective_date AND value <> main.value
)
WHERE
ISNULL(prev.source_id) OR prev.value <> main.value
AND main.value <> 0
ORDER BY main.source_id
As I said: This will have to be adapted to your problem, e.g. by adding proper join conditions for the entity_id.
#Luuk pointed out that you don't need the end date because it can be derived from the data. This would be the case if you had entries for the start of "0 periods" as well, i.e. if there is no value set. If you don't have entries for these, you can't derive the end from the start of the respectively next period since there might be a gap in between.

SQL Multiply values from all previous rows

Refer to the image above.
I have Table 1, and I want to produce Table 2 with SQL.
The first year has to be set to the value 10. The values following will multiply 10 by the multiplier for that year and previous years in Table 1.
For example:
For 2002, the value will be 10 * 2 (2002 multiplier) * 1 (2001 multiplier) = 20.
For 2005, the value will be 10 * 5 * 3 * 1 * 2 * 1 (all previous year multipliers) = 300.
How would I go about doing this? I'd appreciate any help.
A colleague of mine long ago taught me a trick to solve this kind of problems using logarithm properties.
Basically you can do:
Exp(sum(ln(multiplier)))
Edited after the OP made me realize it was incomplete
To do the cumulative logic you need you should apply this on a self-join
select a.youryear, Exp(sum(ln(b.multiplier))) cumulative_mutiplier
from yourtable as a
join
yourtable as b on a.youryear>=b.youryear
group by a.youryear;
I've prepared a test on rextester
create table yourtable (
youryear integer,
multiplier integer
);
insert into yourtable(youryear,multiplier) values (2000,10);
insert into yourtable(youryear,multiplier) values (2001,1);
insert into yourtable(youryear,multiplier) values (2002,2);
insert into yourtable(youryear,multiplier) values (2003,1);
insert into yourtable(youryear,multiplier) values (2004,3);
insert into yourtable(youryear,multiplier) values (2005,5);
select a.youryear, Exp(sum(ln(b.multiplier))) cumulative_mutiplier
from yourtable as a
join
yourtable as b on a.youryear>=b.youryear
group by a.youryear;
The result is:
youryear cumulative_mutiplier
1 2000 10
2 2001 10
3 2002 20
4 2003 20
5 2004 60
6 2005 300
select year
,x
,#result := #result*coalesce(x,10) as result
from table1,(select #result:=1) i
order by year
;
# year, x, result
2000, , 10
2001, 1, 10
2002, 2, 20
2003, 1, 20
2004, 3, 60
2005, 5, 300

Grouping MySQL view in a sequence of rolling dates

I've got two tables:
Table Transmission
------------------------------
Id GroupID Amount Timestamp
1 1 5 2015-05-20 00:00:00
2 1 4 2015-05-19 00:00:00
3 1 10 2015-04-20 00:00:00
4 1 7 2015-04-19 00:00:00
5 1 9 2015-03-20 00:00:00
6 1 2 2015-03-18 00:00:00
Table Group
---------
Id DateCreated BillStart BillStop
1 2015-03-15 2015-05-15 2015-06-14
BillStart and BillStop have a trigger on them that runs daily, if the current Date is greater than BillStop, both BillStart/BillStop increase by a month (so these are effectively the current range we are looking at).
I already have a SQL view that can sum up a range of the transmission entries where the timestamp is between BillStart and BillStop, what I am looking to do is have another view that would effectively hold the sums of transmissions of past months. i.e. if a BillStart/BillStop goes from 2015-05-15 to 2015-06-14, then the view would know to group past transmissions from the ranges of 2015-4-15 to 20-15-14, 2015-3-15 to 2015-4-14, and so on, up until the last range containing the groups creation date.
Ideally the view would look like
-------------------------------------
GroupId Sum BillStart BillStop
1 9 2015-05-15 2015-06-14
1 17 2015-04-15 2015-05-14
1 11 2015-03-15 2015-04-14
Is there a better way to do this?
Another option I was considering was a table for GroupBillRanges that would entail:
GroupBillRange
--------------
Id GroupId BillStart BillStop
1 1 2015-03-15 2015-04-14
2 1 2015-04-15 2015-05-14
3 1 2015-05-15 2015-06-14
And this would be added when each bill range gets updated by the month. With this I would just be able to match all Transmission.GroupId to GroupDateRange.GroupId
Yes, you would need to create the "GroupBillRange" table. Otherwise you lose any record of what the Bill Start/Stop dates were on the old groups. (Sure, you could assume that they are always from the 15th to the 14th. But the one time that they are not, you will have problems.) Once you do that, a query like the following should give you what you're looking for, I believe. (Oh, and you have this question tagged as both SQL Server and MySQL. So I created this script on SQL Server 2008 r2.)
SET NOCOUNT ON;
DECLARE #Transmission TABLE (
ID int,
GroupID int,
Amount int,
TransmissionDate SmallDateTime );
INSERT #Transmission VALUES (1, 1, 5,'2015/05/20');
INSERT #Transmission VALUES (2, 1, 4,'2015/05/19');
INSERT #Transmission VALUES (3, 1,10,'2015/04/20');
INSERT #Transmission VALUES (4, 1, 7,'2015/04/19');
INSERT #Transmission VALUES (5, 1, 9,'2015/03/20');
INSERT #Transmission VALUES (6, 1, 2,'2015/03/18');
DECLARE #TableGroupRange TABLE (
ID int,
GroupID int,
BillStart SmallDateTime,
BillStop SmallDateTime );
INSERT #TableGroupRange VALUES (1, 1, '2015/03/15', '2015/04/14' )
INSERT #TableGroupRange VALUES (2, 1, '2015/04/15', '2015/05/14' )
INSERT #TableGroupRange VALUES (3, 1, '2015/05/15', '2015/06/14' )
SET NOCOUNT OFF;
SELECT TG.GroupID, SUM(T.Amount) as SumAmount, TG.BillStart, TG.BillStop
FROM #TableGroupRange TG
LEFT JOIN #Transmission T ON T.GroupID = TG.GroupID AND T.TransmissionDate BETWEEN TG.BillStart AND TG.BillStop
GROUP BY TG.GroupID, TG.BillStart, TG.BillStop
ORDER BY TG.GroupID, TG.BillStart, TG.BillStop

how to insert and update multiple values at a time

I have 1 table
customer_assignments having customer_id, and category_id columns.
I want to insert multiple category _id's like 1,2,3 by customer_id=62 at a time ..the table look's like
customer_id category_id
62 1
62 2
62 3
suppose if I update category _ids like 1,2 by customer_id=62, the table look's like
customer_id category_id
62 1
62 2
insert and update both will occur at a time....am new to mysql
I need query...
use 2 queries
1.
DELETE * FROM customer_assignments
2.
then now insert waht ever u want using INSERT query

Select distinct user_id from a table for each request type

I have a table with 4 columns:
ID, USER_ID, SOURCE, CREATED_DATE
In that table is the following data:
ID USER_ID SOURCE CREATED_DATE
1 25 PURCHASE 2012-01-01 12:30:00
2 26 PLEDGE 2012-01-01 12:40:00
3 25 PLEDGE 2012-01-01 12:50:00
4 25 PURCHASE 2012-01-14 12:00:00
Now as you can see, I have 4 rows of data, and two unique users. User (25) made 3 transactions (two purchases and one pledge), user (26) made one transaction – (one pledge)
Here is what I am trying to achieve:
I need to select ALL transactions from this table, but I want to select a UNIQUE user for each REQUEST TYPE (source), and that row needs to be the EARLIEST TRANSACTION.
My expected result data would be:
ID USER_ID SOURCE CREATED_DATE
1 25 PURCHASE 2012-01-01 12:30:00
2 26 PLEDGE 2012-01-01 12:40:00
3 25 PLEDGE 2012-01-01 12:00:00
User (25) made TWO PURCHASES (one on 2012-01-01 and one on 2012-01-14) – the first is the one that gets returned.
This is the SQL I have come up with so far:
SELECT
Supporter.user_id,
MIN(Supporter.created) as created,
Supporter.*,
Supporter.source
FROM
supporters AS Supporter
GROUP BY Supporter.source
ORDER BY Supporter.created ASC
Now, this gets me really close, except it only selects ONE of the user id’s (the one with two items – a pledge and a purchase). If I could figure out how to select the data on both users, that would be what I need to do! Can anyone see what I am possibly doing wrong here, or missing?
You need to group by source and by user id
Something like this
SELECT
Supporter.user_id,
MIN(Supporter.created) as created,
Supporter.*,
Supporter.source
FROM
supporters AS Supporter
GROUP BY Supporter.user_id, Supporter.source
ORDER BY Supporter.created ASC