How to assign Column Results to Parameters of a Query - sql

I have a table "Values" The data looks like this:
ID Label Value
1 StartDate 1/1/17
2 EndDate 1/15/17
3 Dept 6
What I'd like to do is load the values of the "Label" column to the corresponding Parameters in my Query:
Declare
#startdate Datetime,
#enddate Datetime,
#DepartmentID int
Select *
From Customers
Where created between #startdate and #enddate and #DepartmentID
How can I assign #Startdate to the 'Startdate' 'value' in the value table? Additionally, Since i'm using different datatypes in my query, than what they are stored in the Values table (Values are 'nvarchar' in values table) Will I run into potential problems?

Declare
#startdate Datetime,
#enddate Datetime,
#DepartmentID int
set #startdate = (Select convert(datetime,[Value]) from dbo.Values where Label='StartDate')
set #enddate = (Select convert(datetime,[Value]) from dbo.Values where Label='EndDate')
set #DepartmentID =(Select convert(int,[Value]) from dbo.Values where Label='Dept')
Select *
From Customers
Where created between #startdate and #enddate and DepartmentId = #DepartmentID

You could try to do something like this:
SELECT
*
FROM
CUSTOMERS
WHERE
CREATED BETWEEN
(SELECT TOP 1 [Value] FROM Values WHERE Label = 'StartDate') --perform casts here if necessary
AND
(SELECT TOP 1 [Value] FROM Values WHERE Label = 'EndDate') --perform casts here if necessary

Related

Array like function for a statement

I have a statement that returns a single number for a date. What I want to do is to be able to execute the statement across a range of dates and get a value for each date.
select dbo.GetItemMTDIssues(inmastx.fac, inmastx.fpartno, inmastx.frev, '6-01-2019')
as MTDiss from inmastx where fpartno='ANF-10-6313-102'
This is how the results look for a single date that I'm getting with my current statement. 6-01-2019
|MTDiss|
600
This is the expected results that I want over a range of dates like 6-01-2019 - 6-05-2019
|MTDiss|
600
450
375
700
300
Also including the function if it's helpful.
CREATE FUNCTION [dbo].[GetItemMTDIssues]
(#fac char(20), #partno char(25), #rev char(3), #currentdate datetime)
returns numeric (15,5)
as
begin
declare #returnval as numeric (15,5)
set #returnval =
isnull(
(select sum(fQty)
from intran
where ftype = 'I'
and month(fdate) = month(#currentdate)
and year(fdate) = year(#currentdate)
and fac = #fac
and fpartno = #partno
and fcpartrev = #rev)
,0.0) * -1
return #returnval
end
You would need first to create the range, and the below t-sql will do that.
declare #startDate datetime='6-01-2019'
declare #endDate datetime='6-05-2019'
;with DateRange as (
select #startDate [date]
union all
select DATEADD(day,1,[date]) [date] from DateRange where [date]<#endDate
)
select * from DateRange
we can test it and see the result to confirm that this is the range we want.
note:if you need to jump by month or number of days other that go day by day you only need to change the code in the DATEADD.
Now we would need to update your function to take the start and end of the range and let it use all the range dates , I think something like the below will help:-
CREATE FUNCTION [GetItemMTDIssuesRange]
(
#fac char(20), #partno char(25), #rev char(3), #startDateRange datetime, #EndDateRange datetime
)
RETURNS TABLE
AS
RETURN
(
with DateRange as (
select #startDateRange [date]
union all
select DATEADD(day,1,[date]) [date] from DateRange where [date]<#EndDateRange
)
--select * from DateRange
select (isnull(sum(fQty),0.0) * -1) MTDiss
from intran
inner join DateRange on year(fdate) = year(DateRange.[date]) and month(fdate) = month(DateRange.[date])
where ftype = 'I'
and fac = #fac
and fpartno = #partno
and fcpartrev = #rev
group by DateRange.[date]
)
GO
Please check it.
if you dont want to change the function this below may help too:-
declare #startDate datetime='6-01-2019'
declare #endDate datetime='6-05-2019'
;with DateRange as (
select #startDate [date]
union all
select DATEADD(day,1,[date]) [date] from DateRange where [date]<#endDate
)
select dbo.GetItemMTDIssues(inmastx.fac, inmastx.fpartno, inmastx.frev, DateRange.[date])
as MTDiss from inmastx,DateRange
where fpartno='ANF-10-6313-102'

Column Invalid in the Selected List

I have this scalar function:
ALTER FUNCTION [dbo].[Custom_SumKayakoMonthProfit]
(#ClientId int, #KKId int,
#StartDate SmallDateTime, #EndDate SmallDatetime,
#Month int)
RETURNS INT
AS
BEGIN
DECLARE #Total INT
SELECT
#Total = ((CAST(SUM(WorkedTimeInMinutes) AS FLOAT) / 60) * KayakoValue)
FROM
[VDBSERVER2012\SQLEXPRESS2014].PlaterITDB.dbo.KayakoTimeEntries
INNER JOIN
ClientContract ON ClientId = #ClientId
AND Workdate BETWEEN ClientContract.StartDt AND ClientContract.EndDt
WHERE
OrganizationID = #KKId
AND WorkDate BETWEEN #StartDate AND #EndDate
AND MONTH(WorkDate) = #Month
RETURN #Total
END
Whenever I try to execute it to use it on a stored procedure, I get this error.
Column 'ClientContract.KayakoValue' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I can't figure out how to solve it.
What don't you understand about the message? You have an aggregation query with no GROUP BY. Hence, all columns must be the arguments to aggregation functions.
I suspect that you intend:
SELECT #Total = CAST(SUM(WorkedTimeInMinutes * KayakoValue) AS FLOAT)/60
FROM [VDBSERVER2012\SQLEXPRESS2014].PlaterITDB.dbo.KayakoTimeEntries kte INNER JOIN
ClientContract cc
ON ClientId = #ClientId AND
Workdate BETWEEN cc.StartDt AND cc.EndDt
WHERE OrganizationID = #KKId AND
WorkDate BETWEEN #StartDate AND #EndDate AND MONTH(WorkDate) = #Month
Note that you should learn to use table aliases and to qualify all column names. This is a good practice for writing readable and maintainable code.
You should use 'KayakoValue' in aggregate function like sum,count, . . . or in group by at the end .
SELECT #Total = ((CAST(SUM(WorkedTimeInMinutes) AS FLOAT)/60) * KayakoValue)
FROM [VDBSERVER2012\SQLEXPRESS2014].PlaterITDB.dbo.KayakoTimeEntries
INNER JOIN ClientContract ON ClientId = #ClientId AND Workdate BETWEEN ClientContract.StartDt AND ClientContract.EndDt
WHERE OrganizationID = #KKId AND WorkDate BETWEEN #StartDate AND #EndDate AND MONTH(WorkDate) = #Month
group by KayakoValue
OR
SELECT #Total = ((CAST(SUM(WorkedTimeInMinutes * KayakoValue) AS FLOAT)/60))
FROM [VDBSERVER2012\SQLEXPRESS2014].PlaterITDB.dbo.KayakoTimeEntries
INNER JOIN ClientContract ON ClientId = #ClientId AND Workdate BETWEEN ClientContract.StartDt AND ClientContract.EndDt
WHERE OrganizationID = #KKId AND WorkDate BETWEEN #StartDate AND #EndDate AND MONTH(WorkDate) = #Month

Showing Data for those Dates which are not present in Database Table

I am trying show attendance record for employees in particular Branch, let Say "Pune Branch".
While Showing Weekly Records, It only shows the record of dates for which there is an entry in database table. I also want to show record for those Date on which there is no any employee present.
Suppose In Log_TB there are 2 employee record present for 28 Apr 2015 out of 2 Employees, Then It Shows
And If No records for that Date then it Returns nothing.
I want result Like
Here is my Query
Declare
#Date date = GETDATE(),
#date1 date,
#Total int
set #date1 = (CONVERT(date,DATEADD(DD,-6,#Date),108));
select #Total = Count(User_TB.User_Id)
from User_TB join Branch_TB
on User_TB.User_Branch = Branch_TB.Branch_Name
where User_TB.User_Branch = 'Pune';
select convert(varchar,Log_TB.Date,106) AS Date,
CONVERT(CHAR(3),DATENAME(weekday,Log_TB.Date)) AS Day,
#Total AS Total,COUNT(Log_TB.User_Id) Present,
(#Total-COUNT(Log_TB.User_Id)) AS Absent
From Log_TB join User_TB on Log_TB.User_Id = User_TB.User_Id
where Log_TB.Date <= (CONVERT(date,#Date,108))
and Log_TB.Date >= #date1 and User_TB.User_Branch = 'Pune'
group by Log_TB.Date;
My table definition
CREATE TABLE [dbo].[Log_TB]
(
[User_Id] [varchar](50) NOT NULL,
[First_Login] [time](0) NULL,
[Logout] [time](0) NULL,
[Date] [date] NULL,
[Working_Hrs] [time](0) NULL,
[extra_Int] [int] NOT NULL,
[extra_String] [varchar](50) NULL
)
What you need is a Numbers or a Date table. You can generate it using something like this
DECLARE #date1 DATE = '20150401',#Date DATE= GETDATE();
;WITH CTE AS
(
SELECT #date1 as datecol
UNION ALL SELECT DATEADD(day,1,datecol) FROM CTE WHERE DATEADD(day,1,datecol) <= #Date
)
SELECT * FROM CTE
In your query, you would use it like this
Declare
#Date date = GETDATE(),
#date1 date,
#Total int
set #date1 = (CONVERT(date,DATEADD(DD,-6,#Date),108));
select #Total = Count(User_TB.User_Id)
from User_TB join Branch_TB
on User_TB.User_Branch = Branch_TB.Branch_Name
where User_TB.User_Branch = 'Pune';
DECLARE #date1 DATE = '20150401',#Date DATE= GETDATE();
;WITH CTE AS
(
SELECT #date1 as datecol
UNION ALL SELECT DATEADD(day,1,datecol) FROM CTE WHERE DATEADD(day,1,datecol) <= #Date
)
select convert(varchar,CTE.datecol,106) AS Date,
CONVERT(CHAR(3),DATENAME(weekday,CTE.datecol)) AS Day,
#Total AS Total,COUNT(User_TB.User_Id) Present,
(#Total-COUNT(User_TB.User_Id)) AS Absent
From CTE LEFT JOIN Log_TB ON Log_TB.Log_TB.Date = CTE.datecol
LEFT join User_TB on Log_TB.User_Id = User_TB.User_Id
and User_TB.User_Branch = 'Pune'
group by CTE.datecol;
Declare #date datetime -- its a starting date
Set #Date = '1-Apr-2015'
Declare #table table (date datetime)
-- inserts data from starting date till getdate
while #date <> convert(datetime,convert(varchar(10),getdate(),101),101)
begin
insert into #table
select #date aa
select #date = #date+1
end
select * from #table
Just join #table and your data with left join
Select *
from #table left join (Your data) with condition date.

SQL Server Stored Procedure Issue. Get Multiple result From Database

Here is my stored procedure to get a list of employees and their hours worked between StartDate and EndDate.
ALTER procedure [dbo].[usp_get_employeehourlyreport]
#startdate datetime,
#enddate datetime
as
begin
select *
from (
select
(select FullName from Registration
where Registration.UserId = UserTime.UserId) Fullname,
ISNULL(SUM(HoursWorked), 0) HoursWorked
from UserTime
where CheckIn between #startdate and #enddate
group by UserId, CheckIn) tbl
end
The result I am getting is :
Fullname HoursWorked
Antonio Jake 0
Antonio Jake 0.016666
So basically it is displaying one row extra with hours 0. I Do not have any duplicate FullName in my database.
Table structures are:
USERTIME:
UserTimeId int Unchecked
UserId int Checked
CheckIn datetime Checked
LoginStatus nvarchar(50) Checked
Day varchar(50) Checked
HoursWorked float Checked
Date nvarchar(50) Checked
REGISTRATION:
UserId int Unchecked
FullName varchar(50) Checked
Try something like this....
ALTER procedure [dbo].[usp_get_employeehourlyreport]
#startdate datetime,
#enddate datetime
AS
BEGIN
SET NOCOUNT ON;
SELECT R.FullName, ISNULL(SUM(UT.HoursWorked),0) AS Total_Hours
FROM Registration R LEFT JOIN USERTIME UT
ON R.UserId = UT.UserId Fullname ,ISNULL(SUM(HoursWorked),0) HoursWorked from UserTime
AND UT.CheckIn >= #startdate
AND UT.CheckIn <= #enddate
GROUP BY R.FullName
END

Remove subquery from JOIN?

In the following query, I would like the remove the subquery from the JOIN statement (since my two SELECT statements are selecting data from same table). How can I use that alias? Thanks in advance for any help.
declare #StartDate datetime= '8/01/2011'
declare #EndDate datetime = '9/20/2011'
declare #PortfolioId int = 6
SELECT
Previous.PreviousNAV,
Todays.TodaysNAV,
ISNULL((Todays.TodaysNAV-Previous.PreviousNAV),0) NetChange,
ISNULL((Todays.TodaysNAV-Previous.PreviousNAV) / Todays.TodaysNAV,0) BAMLIndex
FROM
(
SELECT PortfolioId,ISNULL(NAV,0) PreviousNAV
FROM Fireball..NAV
WHERE Date BETWEEN #StartDate AND #EndDate and PortfolioId = #PortfolioId
) Previous
JOIN
(
SELECT PortfolioId,ISNULL(NAV,0) TodaysNAV
FROM Fireball..NAV
WHERE Date = #EndDate and PortfolioId = #PortfolioId
) Todays
ON Previous.PortfolioId = Todays.PortfolioId
Just eliminate the subqueries entirely. I don't think they add anything to the query. Try this instead:
SELECT
Previous.NAV as PreviousNAV,
Todays.NAV as TodaysNav,
ISNULL((Todays.NAV-Previous.NAV),0) NetChange,
ISNULL((Todays.NAV-Previous.NAV) / Todays.NAV,0) BAMLIndex
FROM
Fireball..NAV as Previous
JOIN
Fireball..NAV as Todays
ON Previous.portfolioID = Todays.PortfolioID
WHERE Previous.Date BETWEEN #StartDate AND #EndDate
AND Previous.PortfolioId = #PortfolioId
AND Todays.Date = #EndDate