How to get total number of columns in stored procedure? - sql-server-2008

SELECT
CONVERT(VARCHAR, b.date, 105) AS 'Date',
m.menucost * (Sum(bm.qty)) AS 'Total'
FROM
billmaster b
LEFT JOIN
billmenumapping bm ON bm.mapbillid = b.billid
LEFT JOIN
menumaster m ON m.menuid = bm.mapmenuid
WHERE
b.date BETWEEN '2015/02/22' AND '2015/02/25'
GROUP BY
b.Date, m.menucost
This code returns the following result:
Date Total
-------------------
23-02-2015 40.00
22-02-2015 40.00
22-02-2015 1800.00
I need the output in a way where totals of date 22-02-2015 dates should be combined and only one result should be given as below. Sum of the total column should be done according to the respective dates.
Date Total
--------------------
23-02-2015 40.00
22-02-2015 1840.00
Please help.

Try this:
SELECT Date,SUM(Total) FROM
(SELECT CONVERT(VARCHAR, b.date, 105) AS 'Date',
m.menucost * (Sum(bm.qty)) AS 'Total'
FROM billmaster b
LEFT JOIN billmenumapping bm
ON bm.mapbillid = b.billid
LEFT JOIN menumaster m
ON m.menuid = bm.mapmenuid
WHERE b.date between '2015/02/22' and '2015/02/25'
GROUP BY b.Date,m.menucost) TempTable
GROUP BY Date

Related

How to Create Dynamic 'Report by Week' Procedure in SQL Server

I am using MySQL . I want to make Stored Procedure for this report.
The query:
select
concat(us.firstname, ' ', us.lastname) as 'Salesperson',
concat(u.firstname, ' ', u.lastname) as 'Borrower Name',
nc.cid as '#Loan Non-Early',
nc.lsum as 'Amount Non-Early',
ec.cid as '#Loan Early',
ec.lsum as 'Amount Early',
(if(nc.cid is null, 0, nc.cid) + if(ec.cid is null, 0, ec.cid)) as '#Loan Total',
(if(nc.lsum is null, 0, nc.lsum) + if(ec.lsum is null, 0, ec.lsum)) as 'Total Amount'
from users u
join borrowers b on b.user_id = u.id
join contracts c on c.borrower_id = b.id
join loans l on l.borrower_id = b.id
join product_industry pi on pi.product_id = l.product_id
left join borrower_sales bs on bs.borrower_id = b.id
left join sales s on s.id = bs.sales_id
left join users us on us.id = s.user_id
left join (
select l.borrower_id as bid, count(l.id) as cid, sum(l.amount) as lsum from loans l
join product_industry pi on pi.product_id = l.product_id
where pi.industry_id = 4
and l.is_early = 0
and date(l.complete_date) between '2022-02-14' and '2022-02-20'
group by l.borrower_id
) nc on nc.bid = b.id
left join (
select l.borrower_id as bid, count(l.id) as cid, sum(l.amount) lsum from loans l
join product_industry pi on pi.product_id = l.product_id
where pi.industry_id = 4
and l.is_early = 1
and date(l.complete_date) between '2022-02-14' and '2022-02-20'
group by l.borrower_id
) ec on ec.bid = b.id
where pi.industry_id = 6
and c.status_id = 882
group by b.id
order by salesperson
;
I cannot figure out how to sort it by week. Can someone please help me what should i do?
I am trying to display my data like:
Salesperson Borrowername LoanNonEarly1 AmountNonEarly1 LoanEarly1 AmountEarly1 Loan Total1 Loan Total1 LoanNonEarly2 AmountNonEarly2 LoanEarly2 AmountEarly2 Loan Total2 Loan Total2 so on...
Calvin Dave 1 100000 0 0 2 100000 0 0
Number 1,2 so on define the number of the week.
SQL Server has the handy DATEPART function.
DECLARE
#dated date = Convert( date, '20220218', 112 )
;
SELECT
Datepart( yy, #dated ) * 100
+ Datepart( isowk, #dated ) AS yearweek
;
I used the year in conjunction with the week as during year changes the week alone might not sort correctly.
In your query there are two dates, one for early and one for non-early payments. This also requires some business logic from you to handle the correct output. So one year-week field for early, then non-early and last a certain week according to business logic.

MySQL query select from multiple table depending on a certain condition

I have two tables as follow:
table internetclient
(id,full_name,location,phone_number)
table internetclientdetails
(incdid,icid,date_sub, date_exp,isPaid,profile_sub)
the data in two table is as follow:
client
--------------------------------------------------------
id full_name location phone_number
-------------------------------------------------------
4 Joe Amine beirut 03776132
5 Mariam zoue beirut 03556133
client_subscription
--------------------------------------------------------------------------
incdid icid date_sub date_exp isPaid sub_price
----------------------------------------------------------------------------
6 4 2018-01-01 2018-01-30 0 2000
7 5 2017-01-01 2017-01-30 0 1000
8 4 2018-03-01 2018-03-30 1 50000
9 5 2018-05-01 2019-05-30 1 90000
note : incdid stands for internetClientDetailsId
and icid stands for internetClientId
Problem
I want to make a query that return client name along with all details depending on the latest client subscription date, the result should be as follow:
------------------------------------------------------------
full_name client_id date_sub sub_price
------------------------------------------------------------
Joe Amine 4 2018-03-01 50000
Mary 5 2018-05-01 90000
What i am tring
SELECT * FROM client c LEFT JOIN client_subscription c_s on c.id=c_s.client_id
UNION
SELECT * FROM client c RIGHT JOIN client_subscription c_S on c.id=c_s.client_id
WHERE
c.sub_date=(SELECT MAX(sub_date) from client_subscription c_s INNER JOIN client c on c.id=c_s.client_id GROUP BY c_s.client_id
i have been working on it all the night. Any help is appreciated a lot.
To get client_subscription for each client you could use a self join
select c.name, a.client_id, a.date_sub, a.sub_price
from client_subscription a
join (
select client_id, max(date_sub) date_sub
from client_subscription
group by client_id
) b on a.client_id = b.client_id and a.date_sub = b.date_sub
join client c on a.client_id = c.id
order by a.date_sub
Demo
Or using left join
select c.name, a.client_id, a.date_sub, a.sub_price
from client_subscription a
left join client_subscription b on a.client_id = b.client_id and a.date_sub < b.date_sub
join client c on a.client_id = c.id
where b.client_id is null
order by a.date_sub
Demo
Using your updated data set updated queries are
select c.full_name, a.icid, a.date_sub, a.sub_price
from internetclientdetails a
join (
select icid, max(date_sub) date_sub
from internetclientdetails
group by icid
) b on a.icid = b.icid and a.date_sub = b.date_sub
join internetclient c on a.icid = c.id
order by a.date_sub;
select c.full_name, a.icid, a.date_sub, a.sub_price
from internetclientdetails a
left join internetclientdetails b on a.icid = b.icid and a.date_sub < b.date_sub
join internetclient c on a.icid = c.id
where b.icid is null
order by a.date_sub
Updated Demo
Hi try below sample might help you.
DECLARE #tblClient AS TABLE (ID INT , Name varchar(100))
DECLARE #tblClientSub As TABLE (id INT,client_id INT,date_sub DATE,sub_price INT)
INSERT INTO #tblClient (id,Name)
VALUES
(1,'Linda'),
(2,'Mary'),
(3,'Joe')
INSERT INTO #tblClientSub(Id,client_id , date_sub , sub_price)
VALUES
(1,1,'2018/01/01',50),
(2,2,'2018/02/01',50),
(3,2,'2018/03/01',30),
(4,2,'2018/04/01',30),
(5,3,'2018/01/01',50),
(6,3,'2018/07/01',50),
(7,1,'2018/02/01',40)
SELECT c.Id,c.Name,cs.date_sub,cs.sub_price
FROM #tblClient c
CROSS APPLY (SELECT TOP (1)date_sub,sub_price
FROM #tblClientSub
WHERE client_id = c.Id
ORDER BY date_sub DESC) cs
select c.name as 'client_name',cs.client_id,max(cs.sub_date) as 'date_sub',cs.sub_price from client c ,
client_subscription cs where cs.client_id=c.id group by cs.client_id,cs.sub_price;
Try this
SELECT c.Name, c.id , MAX(date_sub), sub_price FROM client c LEFT JOIN client_subscription c_s on c.id=c_s.client_id
GROUP BY c.id
ORDER BY c.id ASC

how to get last record of table in sql

I have three entries in the attendance table.But I need to print the last entry of the id from the attendance table.I calculated total duration in separate query and printing list in separate query.Anyone please help me to resolve this.
query to print total duration:
select SEC_TO_TIME(sum(case when a.endtime IS NULL
then time_to_sec(TIMEDIFF(NOW(),a.starttime))
else time_to_sec(a.duration)
end)
) as duration
from attendance a
left join staff s on a.staffid=s.id
left join company c on a.companyid=c.companyid
where DATE_FORMAT(a.createdon, '%Y/%m/%d') = DATE_FORMAT('2017-04-04', '%Y/%m/%d') and
(a.employeecode ='A101' OR 'A101'='') and
(a.companyid=0 OR 0=0)
group by a.employeecode,a.companyid order by a.id desc
Query to print the details:
select a.id,
a.starttime,
a.endtime,
a.startlocation,
a.endlocation,
a.duration,
a.companyid,
a.employeecode,
a.staffid,
a.createdon,
a.createdby,
a.lastmodifiedon,
a.reason,
a.comments,
s.name as staffName,
c.company_name as companyName
from attendance a
left joinstaff s on a.staffid=s.id
left join company c on a.companyid=c.companyid
where DATE_FORMAT(a.created_on, '%Y/%m/%d') = DATE_FORMAT('2017-04-04', '%Y/%m/%d') and
(a.employeecode ='A101' OR 'A101'='') and
(a.company_id=0 OR 0=0)
group by a.employeecode,a.companyid order by a.id desc
I got output by setting the endtime as null.
`select SEC_TO_TIME(sum(case when a.endtime IS NULL then time_to_sec(TIMEDIFF(NOW(),a.starttime)) else time_to_sec(a.duration) end))
from attendance a left join staff s on a.staffid=s.id
left join company c on a.companyid=c.companyid
where DATE_FORMAT(a.createdon, '%Y/%m/%d') = DATE_FORMAT('', '%Y/%m/%d') and
(a.employeecode ='' OR ''='') and
(a.companyid=0 OR 0=0)
group by a.employeecode,a.companyid order by a.id desc`

Trying to add one last SUM() column to my query in SQL Server 2008

I have the first query which is producing correct results. What I need is I need to add the sum of values as a last column grouped by surveyid. I can't insert Sum(c.value) into the first query because it is an aggregate function. I have the correct query as my second query below. I know there's pivot functionality but not sure if it can be used here. I do realize that there will be repetition but that's okay.
'first query
SELECT
A.PATIENTID, B.STUDENTNUMBER, c.surveyid,
convert(varchar, A.CreatedDate, 107),
C.QuestionID, C.Value, D.Question
FROM
dbo.Survey A, dbo.Patient B, [dbo].[SurveyQuestionAnswer] C, [dbo].[LookupQuestions] D
WHERE
A.PATIENTID = B.ID
and c.SurveyID = A.ID
and c.QuestionID = d.ID
and c.questionid <> 10
ORDER BY
A.PATIENTID
'second query
select
c.surveyid,SUM(c.value) as scores
from
dbo.SurveyQuestionAnswer c
group by
c.SurveyID
order by
SurveyID '---not important
You can use SUM if you add the OVER clause. In this case:
SELECT
A.PATIENTID, B.STUDENTNUMBER, c.surveyid,
convert(varchar, A.CreatedDate, 107),
C.QuestionID, C.Value, D.Question,
SUM(c.Value) OVER(PARTITION BY c.surveyid) scores
FROM
dbo.Survey A
INNER JOIN dbo.Patient B
ON A.PATIENTID = B.ID
INNER JOIN [dbo].[SurveyQuestionAnswer] C
ON c.SurveyID = A.ID
INNER JOIN [dbo].[LookupQuestions] D
ON c.QuestionID = d.ID
WHERE
c.questionid <> 10
ORDER BY
A.PATIENTID
You could use something like this:
SELECT
s.PATIENTID, p.STUDENTNUMBER, sqa.surveyid,
CONVERT(varchar, s.CreatedDate, 107),
sqa.QuestionID, sqa.Value, lq.Question,
Scores = (SELECT SUM(Value) FROM dbo.SurveyQuestionAnswer s2 WHERE s2.SurveyID = s.ID)
FROM
dbo.Survey s
INNER JOIN
dbo.Patient p ON s.PatientID = p.ID
INNER JOIN
[dbo].[SurveyQuestionAnswer] sqa ON sqa.SurveyID = s.ID
INNER JOIN
[dbo].[LookupQuestions] lq ON sqa.QuestionID = lq.ID
WHERE
sqa.questionid <> 10
ORDER BY
s.PATIENTID
By having a subquery with the SUM(...) you should be able to get that sum as a single value and you don't need to use any grouping function

MySQL: Using the dates in a between condition for the results

I have a SQL statement in which I do this
... group by date having date between '2010-07-01' and '2010-07-10';
The result looks like:
sum(test) day
--------------------
20 2010-07-03
120 2010-07-07
33 2010-07-09
42 2010-07-10
So I have these results, but is it possible, that I can write a statement that returns me for every day in the "between" condition a result row in this kind:
sum(test) day
--------------------
0 2010-07-01
0 2010-07-02
20 2010-07-03
0 2010-07-04
0 2010-07-05
0 2010-07-06
120 2010-07-07
... ...
42 2010-07-10
Otherwise, if this is not possible, I have to do it in my program logic.
Thanks a lot in advance & Best Regards.
Update: Perhaps it will be better if I will show you the full SQL statement:
select COALESCE(sum(DUR), 0) AS "r", 0 AS "opt", DATE_FORMAT(date, '%d.%m.%Y') AS "day" from (
select a.id as ID, a.dur as DUR, DATE(FROM_UNIXTIME(REVTSTMP / 1000)) as date,
a_au.re as RE, a_au.stat as STAT from b_c
join c on b_c.c_id = c.id
join a on c.id = a.c_id
join a_au on a.id = a_au.id
join revi on a_au.re = revi.re
join (
select a.id as ID, DATE(FROM_UNIXTIME(REVTSTMP / 1000)) as date,
max(a_au.re) as MAX_RE from b_c
join c on b_c.c_id = c.id
join a on c.id = a.c_id
join a_au on a.id = a_au.id
join revi on a_au.re = revi.re
where b_c.b_id = 30 group by ID, date) x on
x.id = a.id and x.date = date and x.MAX_RE = a_au.rev
where a_au.stat != 7
group by ID, x.date)
AS SubSelTable where date between '2010-07-01' and '2010-07-15' group by date;
Update:
My new SQL statement (-> Dave Rix):
select coalesce(`theData`.`real`, 0) as 'real', 0 as 'opt', DATE_FORMAT(`DT`.`ddDate`, '%d.%m.%Y') as 'date'
from `dimdates` as DT
left join (
select coalesce(sum(DUR), 0) AS 'real', 0 AS 'opt', date
from (
select a.id as ID, a.dur as DUR, DATE(FROM_UNIXTIME(REVTSTMP / 1000)) as date, a_au.RE as RE, a_au.stat as STAT
from b_c
join c on b_c.c_id = c.id
join a on c.id = a.c_id
join a_au on a.id = a_au.id
join revi on a_au.RE = revi.RE
join (
select a.id as ID, DATE(FROM_UNIXTIME(REVTSTMP / 1000)) as date, max(a_au.RE) as MAX_RE
from b_c
join c on b_c.c_id = c.id
join a on c.id = a.c_id
join a_au on a.id = a_au.id
join revi on a_au.RE = revi.RE
where b_c.b_id = 30 GROUP BY ID, date
) x
on x.id = a.id and x.date = date and x.MAX_RE = a_au.RE
where a_au.stat != 20
group by ID, x.date
) AS SubTable
where date between '2010-07-01' and '2010-07-10' group by date) AS theData
ON `DT`.`ddDate` = `theData`.`date` where `DT`.`ddDate` between '2010-07-01' and '2010-07-15';
Put the Between Logic in a Where Clause
Select Sum(day), day
From Table
Where day Between date1 and date2
Group By day
EDIT:
Having should only be used to filter data in the aggregates... i.e.
Having Sum(day) > 10
Check out my answer to the following question;
Select all months within given date span, including the ones with 0 values
This may be just what you are looking for :)
You can modify your query above as follows (you could integrate this, but this way is simpler!);
SELECT COALESCE(`theData`.`opt`, 0), `DT`.`myDate`
FROM `dateTable` AS DT
LEFT JOIN (
... INSERT YOUR QUERY HERE ...
) AS theData
ON `DT`.`myDate` = `theData`.`date`
and you will also need to change the DATE_FORMAT(date, '%d.%m.%Y') AS "day" in your query to just date
E.g.
select COALESCE(sum(DUR), 0) AS "r", 0 AS "opt", `date` from
As for #OMG Ponies answer, you will need to pre-populate the dateTable with plenty of rows of data!
Does anyone know how I can post my SQL dump of this table as a file which can be attached? It's quite big, but can be useful...
Assuming that your date column is a DATETIME column, you need to use something to change time values to be the same for proper grouping to happen. IE:
SELECT SUM(t.test),
DATE_FORMAT(t.date, '%Y-%m-%d') AS day
FROM TABLE t
WHERE t.date BETWEEN #start AND #end
GROUP BY DATE_FORMAT(t.date, '%Y-%m-%d')
But if there's no record for a given date, the date will not appear in the result set. In other words, no dates with zero will appear in your output.
To solve that, you need to LEFT JOIN to a table of dates, which MySQL doesn't have the ability to generate. It can't even generate a list of numbers, so you have to create a table with a single column:
DROP TABLE IF EXISTS `example`.`numbers`;
CREATE TABLE `example`.`numbers` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
...and populate it:
INSERT INTO numbers (id) VALUES (NULL)
...before you can use the number value to generate a list of dates using the DATE_ADD function:
SELECT COALESCE(SUM(t.test), 0),
x.the_date AS day
FROM (SELECT DATE_FORMAT(DATE_ADD(NOW(), INTERVAL n.id-1 DAY), '%Y-%m-%d') AS the_date
FROM NUMBERS n) x
LEFT JOIN your_table yt ON DATE_FORMAT(yt.date, '%Y-%m-%d') = x.the_date
WHERE x.the_date BETWEEN #start AND #end
GROUP BY x.the_date