Sum of two sum statements - sql-server-2008

DECLARE #aracct VARCHAR(12)
SET #aracct = '49920813'
DECLARE #item_no VARCHAR(12)
SET #item_no = '2319'
SELECT tran_id, * FROM transactions
WHERE account = #aracct AND item_no = #item_no
/*-----------Use if removing certain items from a check-----------*/
CREATE TABLE itemtable (items VARCHAR(6), account VARCHAR(12))
INSERT INTO itemtable VALUES ('2299', #aracct)
INSERT INTO itemtable VALUES ('2300', #aracct)
--INSERT INTO #itemtable VALUES ('')
DECLARE #tran_id_pmt VARCHAR(6)
SET #tran_id_pmt = '209413'
SELECT I1.result - I2.result AS 'final result'
FROM (SELECT SUM(amt_paid) AS result
FROM transactions
WHERE account = #aracct AND item_no = #item_no) AS I1
JOIN (SELECT SUM(amt_paid) AS result
FROM transactions
WHERE account = #aracct AND item_no = (SELECT items FROM itemtable)) AS I2
ON (I1.account = I2.account)
Trying to get the sum 2 select statements and then sum those 2 statements, but I keep getting an error. Any ideas?

You need include account on your subquery so you can use it on the ON condition
SELECT I1.result - I2.result AS 'final result'
FROM (SELECT account, SUM(amt_paid) AS result
^^^^^^^
FROM transactions
WHERE account = #aracct AND item_no = #item_no
GROUP BY account) AS I1
^^^^^^^^^^^^^^^^
JOIN (SELECT account, SUM(amt_paid) AS result
FROM transactions
WHERE account = #aracct AND item_no = (SELECT items FROM itemtable)
GROUP BY account) AS I2
ON (I1.account = I2.account)
^^^^^^^^
You could also solve it with a conditional aggregation.
SELECT SUM(CASE WHEN item_no = #item_no THEN amt_paid
ELSE 0
END)
-
SUM(CASE WHEN item_no IN (SELECT items FROM itemtable) THEN amt_paid
ELSE 0
END) AS 'final result'
FROM Transactions
WHERE account = #aracct

Related

MySQL Attendance Calculation

Here i have table attendances
I need result as shown below
How can i achieve this in mysql without using any programming language
Sql File is Attendances.sql
We can try a pivot query approach, aggregating by user and date:
SELECT
user_id,
DATE(date_time) AS date,
TIMESTAMPDIFF(MINUTE,
MAX(CASE WHEN status = 'IN' THEN date_time END),
MAX(CASE WHEN status = 'OUT' THEN date_time END)) / 60.0 AS hours
FROM yourTable
GROUP BY
user_id,
DATE(date_time);
The caveats of this answer are many. It assumes that there would be only one IN and OUT entry, per user, per day. If a period could cross over dates, then my answer might not generate correct results. Also, if an IN or OUT value be missing, then NULL would be reported for the hours value.
I have Achieve it my self by creating a mysql function and view
Mysql View
CREATE OR REPLACE VIEW `view_attendances` AS
SELECT
`a`.`id` AS `a1_id`,
`a`.`user_id` AS `user_id`,
CAST(`a`.`date_time` AS DATE) AS `date`,
`a`.`date_time` AS `in`,
`a2`.`id` AS `a2_id`,
`a2`.`date_time` AS `out`,
(TIMESTAMPDIFF(SECOND,
`a`.`date_time`,
`a2`.`date_time`) / 3600) AS `hours`
FROM
(`attendances` `a`
JOIN `attendances` `a2` ON (((`a`.`is_confirm` = 1)
AND (`a`.`status` = 'IN')
AND (`a2`.`id` = FN_NEXT_OUT_ATTENDANCE_ID(`a`.`user_id`, `a`.`date_time`, `a`.`status`))
AND (a2.status = 'OUT')
AND (CAST(`a`.`date_time` AS DATE) = CAST(`a2`.`date_time` AS DATE)))))
Mysql Function
CREATE FUNCTION `fn_next_out_attendance_id`( _user_id INT, _attendance_date_time DATETIME, _status VARCHAR(10) ) RETURNS int(11)
BEGIN
DECLARE _id INT(11);
SELECT
id INTO _id
FROM
attendances
WHERE
is_confirm = 1
AND user_id = _user_id
AND date_time > _attendance_date_time
AND `status` <> _status
ORDER BY
date_time ASC LIMIT 1 ;
RETURN if (_id IS NULL, 0, _id);
END

Multiple Subqueries in where clause

I need two filer data in sub query. This is my sub query one
(select CAST(to_char(date_trunc('day', now()-to_date(max(date_time),'yyyy-MM-dd HH24:mi:ss')), 'dd')AS INT) AS monthDiff FROM loyalty_scheme L
JOIN subscribe_merchant S ON (L.scheme_id = S.schemerefid)
JOIN transaction T ON (S.unipoint_customer_ref_id = T.unipoint_customer_ref_id) where (T.unipoint_customer_ref_id IN( select unipoint_customer_ref_id FROM subscribe_merchant where schemerefid = (SELECT scheme_id from loyalty_scheme where minimum_purchase_amount =(SELECT min(minimum_purchase_amount) from loyalty_scheme where merchant_id = 11 )GROUP BY scheme_id) ) )GROUP BY T.unipoint_customer_ref_id )
it gives int value as a new column
--------
monthDiff
--------
5
---------
370
---------
I need to compare this two value with another sub query and get greater than value. This is the other sub query
((SELECT CAST(to_char(date_trunc('day', to_date(demoting_time_period,'yyyy-MM-dd HH24:mi:ss')), 'dd')AS INT)*31 AS demortProd from loyalty_scheme where minimum_purchase_amount =(SELECT min(minimum_purchase_amount) from loyalty_scheme where merchant_id = 11)GROUP BY scheme_id ))
It returns this as new column
---------------
demortProd
---------------
31
---------------
I need to find greater than 31.
I used where clause as below:
SELECT *
FROM loyalty_scheme L
JOIN subscribe_merchant S ON (L.scheme_id = S.schemerefid)
JOIN transaction T ON (S.unipoint_customer_ref_id = T.unipoint_customer_ref_id) WHERE (select CAST(to_char(date_trunc('day', now()-to_date(max(date_time),'yyyy-MM-dd HH24:mi:ss')), 'dd')AS INT) AS monthDiff FROM loyalty_scheme L
JOIN subscribe_merchant S ON (L.scheme_id = S.schemerefid)
JOIN transaction T ON (S.unipoint_customer_ref_id = T.unipoint_customer_ref_id) where (T.unipoint_customer_ref_id IN( select unipoint_customer_ref_id FROM subscribe_merchant where schemerefid = (SELECT scheme_id from loyalty_scheme where minimum_purchase_amount =(SELECT min(minimum_purchase_amount) from loyalty_scheme where merchant_id = 11 )GROUP BY scheme_id) ) )GROUP BY T.unipoint_customer_ref_id ) <
(SELECT CAST(to_char(date_trunc('day', to_date(demoting_time_period,'yyyy-MM-dd HH24:mi:ss')), 'dd')AS INT) AS demortProd from loyalty_scheme where minimum_purchase_amount =(SELECT min(minimum_purchase_amount) from loyalty_scheme where merchant_id = 11)GROUP BY scheme_id )
but it throws an error:
ERROR: more than one row returned by a subquery used as an expression
Please help me solve this error

SQL: using group by concat()

I have a query which returns result of number of calls made by customers and some suggestions made for customers and etc.. for that particular date ie... grouping it by date
But now I want to find number of customers I tried grouping by lead_id and cuncat(lead_id,timecreatredFormat) still there is a data mismatch
Below is the query that I have tried
select
sum(t.enquiry_cnt),
sum(t.suggested_cnt),
sum(t.tot_cnt)
from
(select
case
when source = 1 then 1
else 0
end enquiry_cnt,
case
when source = 6 then 1
else 0
end suggested_cnt,
case
when (source = 1 || source = 6) then 1
else 0
end tot_cnt,
date_format(timecreated, '%d-%b-%Y') created_time,
lead_id,timecreated
from
mg_lead_suggested_listing group by concat(created_time,lead_id) ) t
group by t.created_time
order by t.timecreated desc
limit 10;
Thanks in advance
Check whether following query is correct or not. I have added COUNT(DISTINCT t.lead_id) to get customer count.
DECLARE #TEMP TABLE
(
[source] INT,
lead_id INT,
timecreated DATETIME
)
INSERT INTO #TEMP VALUES (1,1,GETDATE())
INSERT INTO #TEMP VALUES (6,1,GETDATE())
INSERT INTO #TEMP VALUES (6,1,GETDATE())
INSERT INTO #TEMP VALUES (1,2,DATEADD(d,-1,GETDATE()))
INSERT INTO #TEMP VALUES (1,1,DATEADD(d,-1,GETDATE()))
INSERT INTO #TEMP VALUES (1,1,DATEADD(d,-1,GETDATE()))
SELECT
CAST(t.timecreated AS DATE) [date],
SUM(t.enquiry_cnt) enquiry_cnt,
(SELECT COUNT(DISTINCT lead_id) FROM #TEMP WHERE CAST(timecreated AS DATE) = CAST(t.timecreated AS DATE) AND [source] = 1) as lead_enquiry_cnt,
SUM(t.suggested_cnt) suggested_cnt,
(SELECT COUNT(DISTINCT lead_id) FROM #TEMP WHERE CAST(timecreated AS DATE) = CAST(t.timecreated AS DATE) AND [source] = 6) as lead_suggested_cnt,
SUM(t.tot_cnt) tot_cnt,
COUNT(t.lead_id) as lead_cnt
FROM
(
SELECT
CASE
WHEN [source] = 1 THEN 1
ELSE 0
END enquiry_cnt,
CASE
WHEN [source] = 6 THEN 1
ELSE 0
END suggested_cnt,
CASE
WHEN ([source] = 1 OR [source] = 6) THEN 1
ELSE 0
END tot_cnt,
lead_id,
timecreated
FROM
#TEMP
) AS t
group by
CAST(t.timecreated AS DATE)
order by
[date] desc

IF statement SQL query within the SELECT in MySQL

I have the below stored procedure which works fine.
CREATE DEFINER=`root`#`localhost` PROCEDURE `TxCountByDatePerod`(IN `fromdate` DATE, IN `todate` DATE, IN `department` VARCHAR(20), IN `status` VARCHAR(10), IN `ipg` VARCHAR(20))
SELECT d.dept_name,
s.service_name,
COUNT(*) AS all_row_count
FROM department AS d
INNER JOIN service s ON s.dept_id=d.dept_id
INNER JOIN transaction_detail t ON s.dept_id=t.dept_id
AND s.service_id=t.service_id
WHERE t.tx_begin_date BETWEEN fromdate AND todate
AND (t.dept_id = department
OR department ='null')
AND (t.tx_status = status
OR status ='null')
AND (t.pg_name = ipg
OR ipg ='null')
GROUP BY t.dept_id,
t.service_id
Above SP is written in MySQL to get the number of transactions for a given time duration, provided by a particular service of a particular department. A transactions can be 3 different transaction statuses(tx_status coulmn) which are completed(1), failed(-1), uncompleted(0).
What I'm trying to do is get the data for the report below.
The right now the problem is that all the status are grouped into one row. I tried the below SQL to get the data as needed but it gives out an error that the syntax is not correct.
CREATE DEFINER=`root`#`localhost` PROCEDURE `TxCountByDatePerod`(IN `fromdate` DATE, IN `todate` DATE, IN `department` VARCHAR(20), IN `status` VARCHAR(10), IN `ipg` VARCHAR(20))
SELECT d.dept_name,
s.service_name,
COUNT(*) AS all_row_count,
IF(t.tx_status = 1,
SELECT COUNT(*)
FROM transaction_detail
WHERE tx_status = 1) AS successful_tx_count
FROM department AS d
INNER JOIN service s ON s.dept_id=d.dept_id
INNER JOIN transaction_detail t ON s.dept_id=t.dept_id
AND s.service_id=t.service_id
WHERE t.tx_begin_date BETWEEN fromdate AND todate
AND (t.dept_id = department
OR department ='null')
AND (t.tx_status = status
OR status ='null')
AND (t.pg_name = ipg
OR ipg ='null')
GROUP BY t.dept_id,
t.service_id
Please see the added line below.
IF(t.tx_status = 1, SELECT COUNT(*) FROM transaction_detail WHERE tx_status = 1) AS successful_tx_count is added to the SP.
How can I fix this?
the correct syntax for using an IF statement with a select is like this
CREATE DEFINER=`root`#`localhost` PROCEDURE `TxCountByDatePerod`(IN `fromdate` DATE, IN `todate` DATE, IN `department` VARCHAR(20), IN `status` VARCHAR(10), IN `ipg` VARCHAR(20))
SELECT d.dept_name,
s.service_name,
COUNT(*) AS all_row_count,
IF(t.tx_status = 1,
(SELECT COUNT(*) FROM transaction_detail WHERE tx_status = 1),
0
) AS successful_tx_count
FROM department AS d
INNER JOIN service s ON s.dept_id=d.dept_id
INNER JOIN transaction_detail t ON s.dept_id=t.dept_id
AND s.service_id=t.service_id
WHERE t.tx_begin_date BETWEEN fromdate AND todate
AND (t.dept_id = department
OR department ='null')
AND (t.tx_status = status
OR status ='null')
AND (t.pg_name = ipg
OR ipg ='null')
GROUP BY t.dept_id,
t.service_id
NOTE:
I just put in a default 0 value since you are doing a count but you can change that
IF(t.tx_status = 1
,(SELECT COUNT(*) FROM transaction_detail WHERE tx_status = 1)
,0 -- # -- this can be anything.. you could put in NULL or whatever else if you want
) AS successful_tx_count
you can also use a user defined variable and plug that in like so
SET #a := (SELECT COUNT(*) FROM transaction_detail WHERE tx_status = 1);
and then plug the #a variable in your if statement like so
if(t.tx_status = 1, #a, 0)
See this ARTICLE for more details on the if function
This is your select statement:
SELECT d.dept_name,
s.service_name,
COUNT(*) AS all_row_count,
IF(t.tx_status = 1,
SELECT COUNT(*)
FROM transaction_detail
WHERE tx_status = 1) AS successful_tx_count
Why are you using a subquery here? I suspect that you want the "successful" count to match the same conditions (from the where clause) as the count(*). So, just use conditional aggregation:
SELECT d.dept_name,
s.service_name,
COUNT(*) AS all_row_count,
SUM(t.tx_status = 1) AS successful_tx_count

SQL Stored Procedure fails to update data while the script in it works manually

I have a SQL Script that I execute in a job to transform tables periodically. To speed it up I put that script in a stored procedure and executed it with a job. It worked faster.
The problem occurs at times when the stored procedure even though it executes it doesn't work. I use the script manually and run it and everything works fine.
The whole script is inside a transaction and I have made it so that if some error comes up it gets logged properly. However the script doesn't give any errors.
BEGIN TRANSACTION
BEGIN TRY
-- Rounding off Campaign stats
update Campaigns
set ImpressionsBurned = ImpressionTarget
where ImpressionsBurned > ImpressionTarget and CampaignTypeID = 1
update Campaigns
set ClicksConsumed = ClickTarget
where ClicksConsumed = ClickTarget and CampaignTypeID = 2
-- Updating Campaigns & Banners
update banners
set banners.impressionsburned =
(select sum(impressionsqueue.impressionsburned) from impressionsqueue where impressionsqueue.bannerid = banners.bannerid)
where exists (select impressionsqueue.bannerid from impressionsqueue where impressionsqueue.bannerid = banners.bannerid)
update Campaigns
set ImpressionsBurned =
(select isnull(SUM(ImpressionsQueue.ImpressionsBurned),0) from ImpressionsQueue
inner join Banners on Banners.BannerID = ImpressionsQueue.BannerID and CampaignID = Campaigns.CampaignID
)
where
exists (
(select ImpressionsQueue.BannerID from ImpressionsQueue
inner join Banners on Banners.BannerID = ImpressionsQueue.BannerID and CampaignID = Campaigns.CampaignID
)
)
and
(
( Campaigns.ImpressionsBurned < Campaigns.ImpressionTarget and Campaigns.CampaignTypeID = 1)
or ( Campaigns.ClicksConsumed < Campaigns.ClickTarget and Campaigns.CampaignTypeID = 2)
or Campaigns.CampaignTypeID = 3
)
and Campaigns.IsPaused = 0
and Campaigns.StartsOn <= GetDate() and Campaigns.EndsOn >= GetDate()
-- Updating Paused Banners in the Queue
update ImpressionsQueue
set IsPaused = (
select IsPaused from Banners where Banners.BannerID = ImpressionsQueue.BannerID
)
-- Updating the Navigation URLs
update ImpressionsQueue
set NavigateURL = (
select NavigateURL from Banners where Banners.BannerID = ImpressionsQueue.BannerID
)
-- Removing any rows if the Weight of a banner is updated,
-- the banner will be reinserted later with updated impressions
delete from ImpressionsQueue
where BannerID in
(
select ImpressionsQueue.BannerID from ImpressionsQueue
inner join Banners on Banners.BannerID = ImpressionsQueue.BannerID
group by ImpressionsQueue.BannerID, Banners.Weight
having Banners.Weight <> COUNT(ImpressionsQueue.BannerID)
)
-- Removing entries whose impressions count has reached its target
delete from impressionsqueue where
BannerID in (
select Banners.BannerID from impressionsqueue
inner join Banners on banners.bannerid = impressionsqueue.bannerid
inner join campaigns on campaigns.campaignid = banners.campaignid
where Campaigns.CampaignTypeID = 1
-- excluding flat fee based campaign
group by Campaigns.ImpressionTarget, Banners.BannerID
having not (Campaigns.ImpressionTarget > sum(ImpressionsQueue.impressionsburned))
-- inverse logic for campaign count
)
-- Removing entries whose campaign click count has reached
delete from impressionsqueue where
BannerID in (
select Banners.BannerID from impressionsqueue
inner join Banners on banners.bannerid = impressionsqueue.bannerid
inner join campaigns on campaigns.campaignid = banners.campaignid and Campaigns.CampaignTypeID = 2
and Not (Campaigns.ClickTarget > Campaigns.ClicksConsumed)
-- inverse logic for campaign count
)
-- Removing entries whose campaign has expired
delete from impressionsqueue where
BannerID in (
select impressionqueueid from impressionsqueue
inner join Banners on banners.bannerid = impressionsqueue.bannerid
inner join campaigns on campaigns.campaignid = banners.campaignid
and not (Campaigns.StartsOn <= GETDATE() and Campaigns.EndsOn >= GETDATE())
-- inverse logic for date
)
----------------------------------------------------------------------------------------
-- Begin updating Impressions Queue
----------------------------------------------------------------------------------------
Declare #TempBanners Table(BcID [int] IDENTITY(1,1),ZoneID [int], BannerID [int], Weight [int], FileID [uniqueidentifier], IsPaused [bit], Impressions [int], URL [nvarchar](2048))
/*
Insert into the temp table all the banners that:
1) Belong to an active campaign => c.StartsOn <= GetDate() and c.EndsOn >= GetDate()
2) and Belong to a campaign that is not paused
3) and The banner itself is not paused
4) and Flat Fee campaign banner
*/
Insert Into #TempBanners (ZoneID, BannerID, Weight, FileID, IsPaused, Impressions, URL)
Select
bz.ZoneID,
b.BannerID,
b.Weight,
b.FileID,
b.IsPaused,
b.ImpressionsBurned,
b.NavigateURL
From Banners b
Join Bannerzones bz on b.BannerID = bz.BannerID
Join Campaigns c on b.CampaignID = c.CampaignID
And c.StartsOn <= GetDate() and c.EndsOn >= GetDate()
And c.IsPaused = 0
And b.IsPaused = 0
And (
(c.CampaignTypeID = 1 And c.ImpressionsBurned < c.ImpressionTarget)
Or (c.CampaignTypeID = 2 And c.clicksconsumed < c.clicktarget)
Or (c.campaigntypeid = 3)
);
-- Declaration of Vairables
Declare #index As int,#maxRow As int, #weight Int, #bcid int
Set #index = 1 --Because we will start from First row
Select #maxRow = Count(0) From #TempBanners Where Weight > 1
-- How many rows we have that has weight more then 1
While(#index <= #maxRow)
Begin
Select
#weight = V.Weight,
#bcid = V.BcID
From (
Select
BCid,
Weight,
ROW_NUMBER() Over (Order By Bcid Asc) Row
From #TempBanners
Where Weight > 1
)V
Where V.Row = #index
Set #index = #index + 1
While(#weight <> 1)
Begin
Insert Into #TempBanners (ZoneID, BannerID, Weight, FileID, URL)
Select ZoneID, BannerID, Weight, FileID, URL From #TempBanners Where BcID = #bcid
set #weight = #weight - 1
End
End
-- INSERT INTO THE IMPRESSION QUEUE ALL THE BANNERS THAT ARE NOT YET IN THE QUEUE
Insert Into ImpressionsQueue (BannerID, ZoneID, FileID, ImpressionsBurned, RowUpdated, IsPaused, NavigateURL )
Select V.BannerID, V.ZoneID, V.FileID, V.Impressions, GETDATE(), V.IsPaused, V.URL
From
(
Select m.BannerID, m.ZoneID, m.FileID,
isnull(m.IsPaused,0) as IsPaused,
isnull(m.Impressions,0) as Impressions,
ISNULL(m.URL,'') as URL
From #TempBanners m
where Weight >
(select COUNT(t.bannerid)
from ImpressionsQueue as t
where t.BannerID = m.BannerID
and t.FileID = m.FileID
and t.ZoneID = m.ZoneID
)
)As V;
-- Update the banner file id in case it is modified after the banner was created
Update ImpressionsQueue
Set FileID = CTE.FileID, ImpressionsQueue.IsPaused = isnull(CTE.IsPaused,0), ImpressionsQueue.NavigateURL = CTE.URL
From ImpressionsQueue I
Inner Join #TempBanners As CTE On CTE.BannerID = I.BannerID And CTE.ZoneID = I.ZoneID --And CTE.FileID <> I.FileID
----------------------------------------------------------------------------------------
-- End updating Impressions Queue
----------------------------------------------------------------------------------------
END TRY
BEGIN CATCH
declare #error varchar(3000) = 'Message: ' + ERROR_MESSAGE() + ' ' + ERROR_LINE()
exec master.sys.xp_logevent 50001, #error , 'Warning'
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
IF ##TRANCOUNT > 0
COMMIT TRANSACTION
Not sure if that's the cause of all problem - but if I were you, I'd put the COMMIT TRANSACTION inside the TRY..... block:
-------------------------------------------------------------------------------
-- End updating Impressions Queue
-------------------------------------------------------------------------------
IF ##TRANCOUNT > 0
COMMIT TRANSACTION
END TRY
BEGIN CATCH
declare #error varchar(3000) = 'Message: ' + ERROR_MESSAGE() + ' ' + ERROR_LINE()
exec master.sys.xp_logevent 50001, #error , 'Warning'
IF ##TRANCOUNT > 0
ROLLBACK TRANSACTION
END CATCH
If everything goes okay, you'll execute COMMIT TRANSACTION as the last statement of your TRY... block - and if something blows up, you'll fall into the CATCH block anyway. Might be dangerous to call COMMIT TRANSACTION outside your CATCH block after it....