Insert grouped data - sql

I am getting expected results from my query, I am using group by to group the data on the basis of different Ids.
The problem I am facing is that I have to insert this grouped data in the table called gstl_calculated_daily_fee, but when I pass the grouped result to variables called #total_mada_local_switch_high_value and #mada_range_id and insert them in the table then I get only the last result of the query in the table.
Sample result:
Fee range_id
1.23 1
1.22 2
2.33 3
I get only 2.33 and 1 after I insert but I have to insert the whole result in to the table.
Please suggest how can I insert the whole query result into the table. Below is the query:
DECLARE #total_mada_local_switch_high_value decimal(32,4) = 0.00;
DECLARE #mada_range_id int = 0;
select
#total_mada_local_switch_high_value = SUM(C.settlement_fees),
#mada_range_id = C.range_id
From
(
select
*
from
(
select
rowNumber = #previous_mada_switch_fee_volume_based_count + (ROW_NUMBER() OVER(PARTITION BY DATEPART(MONTH, x_datetime) ORDER BY x_datetime)),
tt.x_datetime
from gstl_trans_temp tt where (message_type_mapping = 0220) and card_type ='GEIDP1' and response_code IN(00,10,11) and tran_amount_req >= 5000
) A
CROSS APPLY
(
select
rtt.settlement_fees,
rtt.range_id
From gstl_mada_local_switch_fee_volume_based rtt
where A.rowNumber >= rtt.range_start
AND (A.rowNumber <= rtt.range_end OR rtt.range_end IS NULL)
) B
) C
group by CAST(C.x_datetime AS DATE),C.range_id
-- Insert Daily Volume
INSERT INTO
gstl_calculated_daily_fee(business_date,fee_type,fee_total,range_id)
VALUES
(#tlf_business_date,'MADA_SWITCH_FEE_LOCAL_CARD', #total_mada_local_switch_high_value, #mada_range_id)

I see no need for variables here. You can insert the aggregated results directly.
Sample data
create table Data
(
Range int,
Fee money
);
insert into Data (Range, Fee) values
(1, 1.00),
(1, 0.50),
(2, 3.00),
(3, 0.25),
(3, 0.50);
create table DataSum
(
Range int,
FeeSum money
);
Solution
insert into DataSum (Range, FeeSum)
select d.Range, sum(d.Fee)
from Data d
group by d.Range;
Fiddle to see things in action.

Related

An aggregate may not appear in the set list of an UPDATE statement T-SQL

In T-SQL I'm attempting to update a stock user field with the number of weeks we expect it to be delivered to us by taking the difference between today and the purchase order due in dates. However the select query can return more than one line of purchase orders if there is more than one purchase order containing that product (obviously). I would like to take the smallest number it returns / minimum value but obviously cannot do this within the update query. Can anyone recommend a workaround? Thanks.
UPDATE [Exchequer].[ASAP01].[STOCK]
SET stUserField7 = DATEDIFF(day,CONVERT(VARCHAR(8), GETDATE(), 112),min(tlLineDate)) / 7 + 1
FROM [Exchequer].[ASAP01].[STOCK]
JOIN [Exchequer].[ASAP01].[CUSTSUPP]
ON stSupplier = acCode
JOIN [Exchequer].[ASAP01].[DETAILS]
ON stCode = tlStockCodeTrans1
WHERE stSupplier <> '' AND stQtyOnOrder > '0' AND stQtyOnOrder > stQtyAllocated
AND tlOurRef like 'POR%' AND (floor(tlQtyDel) + floor(tlQtyWOFF)) < floor(tlQty)
AND tlLineDate >= CONVERT(VARCHAR(8),GETDATE(), 112)
Why are you casting date to varchar for the difference?
This is not date but how you can use a window function in an update
declare #maps table(name varchar(10), isUsed bit, code varchar(10));
insert into #Maps values
('NY', 1, 'NY1')
, ('NY', 0, 'NY2')
, ('FL', 0, 'FL1')
, ('TX', 0, 'TX1')
declare #Results table (id int identity primary key, Name varchar(20), Value int, Code varchar(20), cnt int)
insert into #results values
('FL', 12, 'FL1', null)
, ('TX', 54, 'TX1', null)
, ('TX', 56, 'TX1', null)
, ('CA', 50, 'CA1', null)
, ('NJ', 40, 'NJ1', null)
select * from #results
order by name, Value desc
update r
set r.cnt = tt.cnt
from #results r
join ( select id, max(value) over (partition by name) as cnt
from #Results
) tt
on r.id = tt.id
select * from #results
order by name, value desc
Build a SELECT query with columns for the following:
The primary key of the [Exchequer].[ASAP01].[STOCK] table
The new desired stUserField7
Given the MIN(tlLineDate) expression in the original question, if this SELECT query does not have either a GROUP BY clause or change to use an APPLY instead of a JOIN, you've probably done something wrong.
Once you have that query, use it in an UPDATE statement like this:
UPDATE s
SET s.stUserField7 = t.NewValueFromSelectQuery
FROM [Exchequer].[ASAP01].[STOCK] s
INNER JOIN (
--- your new SELECT query here
) t ON t.<primary key field(s)> = s.<primary key field(s)>

SQL update one single row table with data from another

I have two tables. The first one with all movements in twelve months and the second one with claims registered in the same period of time. When I run the following query from the first table I've got 10 records. Of course, there are other records with a different number of movements (e.g.: 7, 23, 2 movements):
select t.cod_suc
,t.cod_ramo_comercial
,t.Poliza
,t.Item
,t.id_pv
from temp_portafolio_personal_accidents as t
where t.cod_suc = 2
and t.cod_ramo_comercial = 46
and t.Poliza = 50283
and t.Item = 1
and t.id_pv = 788383;
With the second query, for the second table, I have the following results:
select c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident]
,max(c.id_pv) as id_pv
,count(distinct [No. Incident]) as 'Conteo R12'
from #claims as c
where c.[ID Incident] = 343632
group by c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident];
Now, I need to update the first table but only one record. I'm using the following query, but all records are being updated. When I sum results I have 10 but is just one claim, as the second query shows.
update p
set [No. Siniestros R12] = b.[Conteo R12]
from temp_portafolio_personal_accidents p
left join
(select c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident]
,max(c.id_pv) as id_pv
,count(distinct [No. Incident]) as 'Conteo R12'
from
#claims as c
where c.[ID Incident] = 343632
group by c.cod_suc
,c.cod_ramo_comercial
,c.[No. Policy]
,c.Item
,c.[ID Incident]
) b
on p.id_pv = b.id_pv
and p.cod_suc = b.cod_suc
and p.cod_ramo_comercial = b.cod_ramo_comercial
and p.Poliza = b.[No. Policy]
and p.Item = b.Item
where p.id_pv = 788383;
You can use a CTE with a ROW_NUMBER() function to do this. Simple example:
DECLARE #TABLE AS TABLE (Testing INT, Testing2 VARCHAR(55), Testing3 BIT);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
INSERT INTO #TABLE VALUES (1, '1', 1);
WITH CTE AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY Testing) AS RowID
,Testing
,Testing2
,Testing3
FROM #TABLE
)
UPDATE CTE
SET Testing = 2, Testing2 = '2', Testing3 = 0
WHERE RowID = 1
;
SELECT * FROM #TABLE
;

Count number of records returned by temp table - SQL Server

My script is as below
CREATE TABLE #t (Id int, Name varchar(10))
INSERT INTO #t VALUES (1, 'A')
INSERT INTO #t VALUES (1, 'B')
INSERT INTO #t VALUES (1, 'C')
INSERT INTO #t VALUES (1, 'D')
INSERT INTO #t VALUES (2, 'E')
SELECT COUNT(0)FROM (SELECT COUNT(0) FROM #t GROUP BY Id) a
but I am getting an error
Msg 8155, Level 16, State 2, Line 5
No column name was specified for column 1 of 'A'.
When you use a subquery, all the columns need to given names:
SELECT COUNT(0)
FROM (SELECT COUNT(0) as cnt FROM #t GROUP BY Id
) a;
However, a simpler way to write this is:
SELECT COUNT(DISTINCT id)
FROM #t;
Actually, this isn't exactly the same. Your version will count NULL values but this does not. The exact equivalent is:
SELECT COUNT(DISTINCT id) + MAX(CASE WHEN id IS NULL THEN 1 ELSE 0 END)
FROM #t;

using row_number to return specific rows of query

I am using SQL Server 2012 & MATLAB. I have a table of 5 columns (1 char, 1 datetime and 3 floats). I have a simple query shown below that returns the data from this table which contains over a million records - this however causes an out of memory error in MATLAB.
simple query
select id_co, date_r, FAM_Score, FAM_A_Score, FAM_Score
from GSI_Scores
where id_co <> 'NULL'
order by id_co, date_rating
So I was looking to breakdown the query select the data in batches of 250,000 records. I have just come across the ROW_NUMBER function which I added to my query, please see below. This numbers all the records for me. However I am having trouble selecting say records between 250,000 and 500,000. How do I do this?
updated query
select id_co, date_r, FAM_Score, FAM_A_Score, FAM_Score, row_number() over (order by id_co) as num_co
from GSI_Scores
where id_co <> 'NULL' and num_sedol between 250000 and 500000
order by id_co, date_rating
Simply use a sub query or Common Table Expression (CTE).
;WITH CTE AS
(
--Your query
)
SELECT * FROM CTE
WHERE num_co BETWEEN 250000 AND 500000
Just an sample example
declare #t table (ID INT)
insert into #t (id)values (1)
insert into #t (id)values (2)
insert into #t (id)values (3)
insert into #t (id)values (4)
;WITH CTE AS
(
select *,COUNT(ID)OVER (PARTITION BY ID ) RN from #t
)
Select ID from CTE C WHERE C.ID BETWEEN 2 AND 4
ORDER BY RN
OR
;WITH CTE (select id_co,
date_r,
FAM_Score,
FAM_A_Score,
FAM_Score,
COUNT(id_co) over (PARTITION BY ID DESC) as num_co
from GSI_Scores
where id_co <> 'NULL')
Select C.d_co,
C.date_r,
C.FAM_Score,
C.FAM_A_Score,
C.FAM_Score FROM CTE C
WHERE C.id_co between 250000 and 500000
order by C.id_co, C.date_rating
You could try using the OFFSET x ROWS FETCH NEXT y ROWS ONLY commands like this:
CREATE TABLE TempTable (
TempID INT IDENTITY(1,1) NOT NULL,
SomeDescription VARCHAR(255) NOT NULL,
PRIMARY KEY(TempID))
INSERT INTO TempTable (SomeDescription)
VALUES ('Description 1'),
('Description 2'),
('Description 3'),
('Description 4'),
('Description 5'),
('Description 6'),
('Description 7'),
('Description 8'),
('Description 9'),
('Description 10')
SELECT * FROM TempTable ORDER BY TempID OFFSET 3 ROWS FETCH NEXT 2 ROWS ONLY;

Returning a set of the most recent rows from a table

I'm trying to retrieve the latest set of rows from a source table containing a foreign key, a date and other fields present. A sample set of data could be:
create table #tmp (primaryId int, foreignKeyId int, startDate datetime,
otherfield varchar(50))
insert into #tmp values (1, 1, '1 jan 2010', 'test 1')
insert into #tmp values (2, 1, '1 jan 2011', 'test 2')
insert into #tmp values (3, 2, '1 jan 2013', 'test 3')
insert into #tmp values (4, 2, '1 jan 2012', 'test 4')
The form of data that I'm hoping to retrieve is:
foreignKeyId maxStartDate otherfield
------------ ----------------------- -------------------------------------------
1 2011-01-01 00:00:00.000 test 2
2 2013-01-01 00:00:00.000 test 3
That is, just one row per foreignKeyId showing the latest start date and associated other fields - the primaryId is irrelevant.
I've managed to come up with:
select t.foreignKeyId, t.startDate, t.otherField from #tmp t
inner join (
select foreignKeyId, max(startDate) as maxStartDate
from #tmp
group by foreignKeyId
) s
on t.foreignKeyId = s.foreignKeyId and s.maxStartDate = t.startDate
but (a) this uses inner queries, which I suspect may lead to performance issues, and (b) it gives repeated rows if two rows in the original table have the same foreignKeyId and startDate.
Is there a query that will return just the first match for each foreign key and start date?
Depending on your sql server version, try the following:
select *
from (
select *, rnum = ROW_NUMBER() over (
partition by #tmp.foreignKeyId
order by #tmp.startDate desc)
from #tmp
) t
where t.rnum = 1
If you wanted to fix your attempt as opposed to re-engineering it then
select t.foreignKeyId, t.startDate, t.otherField from #tmp t
inner join (
select foreignKeyId, max(startDate) as maxStartDate, max(PrimaryId) as Latest
from #tmp
group by foreignKeyId
) s
on t.primaryId = s.latest
would have done the job, assuming PrimaryID increases over time.
Qualms about inner query would have been laid to rest as well assuming some indexes.