I have 4 tables from which I am fetching records. The first three tables required inner join with the common rows but with 4th table I need left outer join because I have to preserve the already fetched rows from first three tables.
Now, problem is that I want left join with fourth table but it should only pick the records having date = current date. I am passing current date from C# while calling my stored procedure. But the thing is SQL Server is giving null records.
Here is the query::
alter procedure
(#currentdate varchar(50))
select distinct
table1.name, table2.class,table3.stream
from
table1
inner join
table 2 on table1.id = table2.id
inner join
table3 on table3.id=table2.id
left outer join
table 4 on table 4.id = table3.id and table4.date = #currentdate
I used and with left outer join because I want records in that way where as using where clause filters the whole result and just give me one record.
Then also I used casting with both the dates in stored procedure but no positive response.
From C# I'm using
var date = datetime.now.toshortdate();
CallStoredProcedure(date)
Please help me regarding this ASAP. Thank you
First of all - you should use the appropriate type for your dates - that is DATETIME - do not cast dates into strings and back if you can avoid it! (and you can definitely avoid it here)
Secondly: the DATETIME in SQL Server as well as the DateTime in .NET both have dates and time information, e.g. 2013-06-23 14:57:34 so if you're doing an equality comparison in your JOIN condition, only those rows that exactly match your date and time will be selected. So you need strip off the time portion, if you want to use just dates for comparison.
So try this code here:
ALTER PROCEDURE dbo.YourProcedureNameHere (#currentdate DATETIME)
SELECT DISTINCT
table1.name, table2.class, table3.stream
FROM
dbo.table1
INNER JOIN
dbo.table2 ON table1.id = table2.id
INNER JOIN
dbo.table3 ON table3.id = table2.id
LEFT OUTER JOIN
table 4 ON table 4.id = table3.id
AND DATEADD(DAY, DATEDIFF(DAY, 0, table4.date), 0) =
DATEADD(DAY, DATEDIFF(DAY, 0, #currentdate), 0)
This strips off the time portion of your table4.date as well as #currentdate and then the comparison will be done on just the date (no time involved). Once you've updated to SQL Server 2008 or newer, I would recommend to use the DATE datatype which is designed exactly for this - storing just the date (no time). Unfortunately, that's not yet available in SQL Server 2005.
Also, from C# - use this line to call your stored procedure:
var date = Datetime.Today;
CallStoredProcedure(date);
Related
These are the tables that I have created: Tables
I want to get accounts.account,accounts.type,DATE(transactions.date),transactions.transactionid,transactions.amount,transactions.note from two tables between '10-11-2021' and '31-12-2021'.(whatever type may be)
I want to get Sum(account) from transactions table where type="income" and between '10-11-2021' and '31-12-2021'.
I want to get Sum(account) from transactions table where type="expense" and between '10-11-2021' and '31-12-2021'.
But I need all three queries in a single statement(that's what I am struggling)
My query:
SELECT accounts.account,accounts.type,DATE(transactions.date),transactions.transactionid,transactions.amount,transactions.note
FROM transactions
FULL JOIN accounts ON transactions.accountid=accounts.accountid
WHERE transactions.date BETWEEN '{0}' AND '{1}' ORDER BY transactions.date
UNION
select sum(amount)
FROM transactions
FULL JOIN accounts ON transactions.accountid=accounts.accountid
WHERE accounts.type='income'
I need to add other two queries also to fit above
can anyone help me?
Given the poor information about the source tables, the best I could is the following:
SELECT
a.account,
a.type,
DATE(t.date),
sum(case when t.type = 'income' then t.amount else 0 end) sum_of_income,
sum(case when t.type = 'expense' then t.amount else 0 end) sum_of_expense
FROM transactions t
left JOIN accounts a
ON t.accountid = a.accountid
group by
a.account,
a.type,
DATE(t.date)
tip: you shouldn't write your sql script in single-line code, almost never.
Also could be more informative to have table contents, or at least screenshots.
Working with a left join on an Oracle DB is causing some interesting data issues to be returned when using Linq2Db as the mapping layer.
SELECT * FROM REBATE_HISTORY frh
LEFT JOIN PAYMENT fp
ON frh.TRANSACTION_REFERENCE_NUMBER = fp.TRANSACTION_REFERENCE_NUMBER
Running this select against a specific Rebate year entry returns 8 entries from the database table, due to 3 years not having associated payments. However the following linq statement:
from rebateHistory in database.RebateHistory
join payments in database.Payments
on rebateHistory.ReferenceNumber equals payments.ReferenceNumber into paymentHistory
from payment in paymentHistory.DefaultIfEmpty()
Causes the following SQL query to be generated which in turn returns 3000+ entries
FROM REBATE_HISTORY rebateHistory
LEFT JOIN PAYMENT paymentHistory
ON (rebateHistory.TRANSACTION_REFERENCE_NUMBER IS NULL AND paymentHistory.TRANSACTION_REFERENCE_NUMBER IS NULL
OR rebateHistory.TRANSACTION_REFERENCE_NUMBER = paymentHistory.TRANSACTION_REFERENCE_NUMBER )
What is going wrong that the generated SQL is including the IS NULL check for both column values?
As was pointed out by svyatoslav-danyliv the configuration for Linq2Db by default uses CompareNullsAsValues which causes the generated SQL to include null checks on both fields.
The fix is in the constructor of your DataConnection object to define:
Linq2Db.Common.Configuration.Linq.CompareNullsAsValues = false
I want to create a SQL query that will do the counting for me instead of in the razor code, I want to calculate the amount of distinct dates in my database.
I found that SQL Server CE does not support count(distinct column_name) and instead using group by would be the solution, but for some reason I could not make it work, what am I doing wrong?
SELECT COUNT(date) as date
FROM Test
GROUP BY date
This simply counted every date in my database and not the distinct ones when writing it out like the following
var totalcount = 0;
foreach (var c in db.Query(query))
{
var ttotalcount = c.date;
totalcount += ttotalcount;
}
<a>#totalcount<a>
Updated
Your query is asking for the counts of each distinct date. If you want to know how many of those you have you need to sum them up. You can do this be nesting your query with a SUM query. Then use an additional column defulted to "1", to allow to sum up the number of rows (which should be your distinct dates). Also date can be a reserved word. You might want to try and avoid using that as a column name.
SELECT SUM(New_Row) as dateSUM from (
SELECT COUNT(date) as dateCount, 1 as New_Row FROM Test GROUP BY date
) a
Maybe:
SELECT COUNT(date) as [date]
FROM Test
GROUP BY date
Date is a reserved word, need to add []
You are confusing SQL with the three usages of date. I am assuming that the original field is named date. I am also assuming that each record has the date field populated.
SELECT COUNT(*) as numDates FROM Test GROUP BY date
I have written a SQL query which search the employee ATTENDANCE Table for the persons who are absent. But how can I show the dates I mean the date of the absent period? It works fine except the date. I want to show what's the day of that absent period? I am unable to show the date.
Sample:
BadgeNumber - EmployeeName - Absent Date
10042 - Mr. Erik - 2014-07-01
Code:
SELECT SMEmployee.BadgeNumber,SMEmployee.EmployeeFullName,SMDepartment.DepartmentName
FROM SMEmployee
LEFT OUTER JOIN SMDepartment
ON SMDepartment.DepartmentID=SMEmployee.DepartmentID
WHERE EmployeeID NOT IN (
SELECT empCheckInOut.USERID
FROM empCheckInOut
WHERE convert(date,CHECKTIME)='2014-07-01')
Normally to check for the lack of existence of a record (as you are doing here for attendence, checking the employee did not check in / out on a day) it is more efficient to use a LEFT OUTER JOIN and the check for NULL in one of the fields in the WHERE clause (ie, a LEFT JOIN where no row found).
However this also won't give you the date.
I presume that you want to check a selection of dates, and this need to pull through the date they were absent.
As such maybe use a series of unioned simple queries to get the dates, CROSS JOIN that to your employee table and LEFT JOIN it to the empCheckInOut table. This way you can put out the date.
SELECT SMEmployee.BadgeNumber,SMEmployee.EmployeeFullName,SMDepartment.DepartmentName, subDate.aDate
FROM SMEmployee
CROSS JOIN (SELECT '2014-07-01' AS aDate UNION SELECT '2014-06-30') subDate
LEFT OUTER JOIN SMDepartment
ON SMDepartment.DepartmentID=SMEmployee.DepartmentID
LEFT OUTER JOIN empCheckInOut
ON SMEmployee.EmployeeID = empCheckInOut.USERID
AND convert(date,CHECKTIME) = subDate.aDate
WHERE empCheckInOut.USERID IS NULL
It seems that you capture the days employee is present in 'empCheckInOut' table.
You need to construct temp table with all the dates lets say of 1 month and then minus the dates that are captured in 'empCheckInOut' table.
e.g. #temp will have 06-01-2014, 06-02-2014, 06-03-2014, ... (all 30 days of Jun)
CheckInOut will have 06-01-2014, 06-03-2014,... (emp is absent on 2nd Jun, so total 29 days of Jun captured here)
Then, subtract one from the other and you will get dates when employee is absent.
I have a List of UserID's and a open connection to SQL Server. How can I loop through this List and Select matching UserID with First_Name and Last_Name columns? I assume the output can be in a datatable?
many thanks
It varies slightly depending on which type of SQL you're running, but this and this should get you started.
The most expedient way of doing this would be to:
Turn the List into a string containing a comma separated list of the userid values
Supply that CSV string into an IN clause, like:
SELECT u.first_name,
u.last_name
FROM USER_TABLE u
WHERE u.userid IN ([comma separated list of userids])
Otherwise, you could insert the values into a temp table and join to the users table:
SELECT u.first_name,
u.last_name
FROM USER_TABLE u
JOIN #userlist ul ON ul.userid = u.userid
Write a function in your SQL database named ParseIntegerArray. This should convert a comma delimited string into a table of IDs, you can then join to this in your query. This also helps to avoid any SQL injection risk you could get from concatenating strings to build SQL. You can also use this function when working with LINQ to SQL or LINQ to Entities.
DECLARE #itemIds nvarchar(max)
SET itemIds = '1,2,3'
SELECT
i.*
FROM
dbo.Item AS i
INNER JOIN dbo.ParseIntegerArray(#itemIds) AS id ON i.ItemId = id.Id
This article should help you: http://msdn.microsoft.com/en-us/library/aa496058%28SQL.80%29.aspx
I've used this in the past to create a stored procedure accepting a single comma delimited varchar parameter.
My source from the C# program was a checked list box, and I built the comma delimited string using a foreach loop and a StringBuilder to do the concatenation. There might be better methods, depending on the number of items you have in your list though.
To come back to the SQL part, the fn_Split function discussed in the article, enables you to transform the comma delimited string back to a table variable that SQL Server can understand... and which you can query in your stored procedure.
Here is an example:
CREATE PROCEDURE GetSelectedItems
(
#SelectedItemsID Varchar(MAX) -- comma-separated string containing the items to select
)
AS
SELECT * FROM Items
WHERE ItemID IN (SELECT Value FROM dbo.fn_Split(#SelectedItemsIDs,','))
RETURN
GO
Note that you could also use an inner join, instead of the IN() if you prefer.
If you don't have the fn_Split UDF on your SQL Server, you can find it here: http://odetocode.com/Articles/365.aspx
I hope this helps.