Inner Join Query incorrect result - c#

Hi I am developing an application in VS 2010, C# and SQLCe database.
I am generating a report from 3 tables respectively Income, Expence and Transactions.
table structure is as below:
Income:
Expence:
Transactions:
For this I wrote query
select t.tDate as [Date], t.tDescription as [Detail],e.eAmount as [Debit],
i.iAmount as [Credit], t.balance as [Balance]
from Transactions t
inner join Expence e on t.pid=e.pid
join Income i on t.pid=i.pid
where t.pid='11'
But when I run this query I am just getting
I want that my result should be like a bank statement as below.
As per my understanding query is not right.
How can we write query to get result like this?

You must use the left join, not use Join. Because left return all cases in table from and case exists in table Expence e Income.
select t.tDate as [Date], t.tDescription as [Detail],e.eAmount as [Debit],
i.iAmount as [Credit], t.balance as [Balance]
from Transactions t
left join Expence e on t.pid=e.pid
left join Income i on t.pid=i.pid
where t.pid='11'

If I got it right to join items from Expence table with items from Transactions table you should use pId and eId and to join items from Income you should use pId and iId, so your select would look something like that:
select t.tDate as [Date], t.tDescription as [Detail],e.eAmount as [Debit],
i.iAmount as [Credit], t.balance as [Balance]
from Transactions t
inner join Expence e on t.pid=e.pid and t.eId = e.eId
join Income i on t.pid=i.pid and t.iId = i.iId
where t.pid='11'

Related

Return Top 1 from any SQL query/view/CTE

Is there a way to return only ONE record so that I can get all the column calls via the code below?
using (var reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess).ConfigureAwait(false))
{
DataTable dtResults = new DataTable();
dtResults.Load(reader);
return dtResults;
}
So right now this will return ALL X records from the query and I only need to return 1 record so I can plug the columns data types etc. into my Grid control.
We can't just add SELECT Top 1 because some of the queries start with a CTE etc.
We can't wrap it around another query because sometimes the query have Order Bys
We can't force the users to add a separate query that will mimic what we want to do.
Here is the error:
Msg 1033, Level 15, State 1, Line 40
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
Here is the query:
SELECT TOP 1 *
FROM
(SELECT O.Department, O.ID
FROM dbo.table1 e
LEFT JOIN dbo.table2 O ON e.Department = O.Department
ORDER BY ID) x
If you need metadata only, use .ExecuteReader(System.Data.CommandBehavior.SchemaOnly)
If you want to read one row, use SQL's OFFSET/FETCH clause. They are appended at the end of the statement, so might work for your case.
https://learn.microsoft.com/en-us/sql/t-sql/queries/select-order-by-clause-transact-sql?view=sql-server-ver15
Note that you must provide some ordering clause.
SELECT
O.Department
,O.ID
FROM dbo.table1 e
LEFT JOIN dbo.table2 O
ON e.Department = O.Department
order by O.ID
OFFSET 0 ROWS FETCH NEXT 1 ROWS ONLY
Try the following, you cannot use Order by with sub-query in SQL server.
select top 1 *
from
(
SELECT
O.Department
,O.ID
FROM dbo.table1 e
LEFT JOIN dbo.table2 O
ON e.Department = O.Department
)
Order by
ID
The subquery is just unecessary. You can use top (1) and order by directly in the outer query:
select top(1) o.department, o.id
from dbo.table1 e
left join dbo.table2 o on e.department = o.department
order by id
sp_describe_first_result_set should do what you want. It'll return metadata for the command in question.
exec sp_describe_first_result_set #tsql = N'SELECT O.Department, O.ID
FROM dbo.table1 e
LEFT JOIN dbo.table2 O ON e.Department = O.Department
ORDER BY ID'

Query taking too long to execute in LINQ

I've written a query which should take all the rows from one table and do a subquery to a second table pulling only one value from the most recent record. In SQL Server the query takes about 15 seconds to execute and the LINQ query takes close to 2 minutes. Can someone help me with translating the SQL to LINQ, I must have done something wrong along the way.
The SQL:
SELECT a.isrunning,
worktype = (
SELECT TOP 1
w.worktype
FROM dbo.workorder w WITH (NOLOCK)
WHERE w.assetnum = a.assetnum
ORDER BY w.statusdate DESC
),
a.status,
*
FROM dbo.asset a WITH (NOLOCK)
WHERE a.assetnum IN ('list', 'of', 'asset', 'numbers')
The LINQ Query:
(
from a in db.assets
let wo = (
from w in db.workorders
where w.assetnum == a.assetnum
orderby w.statusdate descending
select w).FirstOrDefault()
where aliasStrings.Contains(a.assetnum)
select new AssetWithWorkType {
...
}
);
It is recommended to have indexes on foreign keys. Also indexes that covers filtering and ordering clauses. So I suggest you to create the following 3 indexes:
CREATE NONCLUSTERED INDEX [IDX_workorder_statusdate] ON dbo.workorder(statusdate)
CREATE NONCLUSTERED INDEX [IDX_workorder_assetnum] ON dbo.workorder(assetnum)
If assetnum column in asset table is not the primary key then additionally:
CREATE NONCLUSTERED INDEX [IDX_asset_assetnum] ON dbo.asset(assetnum)
You can create a temp table for the correlated subquery results, and then join it later. Syntax is not correct, as I dont have your table schemas or data, but the idea is the same.
CREATE TABLE #workTypes (worktype VARCHAR(X), assetnum VARCHAR(x))
INSERT INTO #workTypes
SELECT TOP 1 worktype, assetnum FROM dbo.workorder ORDER BY statusdate DESC
SELECT a.isrunning,
b.worktype,
a.status,
*
FROM dbo.asset a WITH (NOLOCK)
INNER JOIN #worktypes b
ON a.assetnum = b.assetnum
WHERE a.assetnum IN ('list', 'of', 'asset', 'numbers')
How about:
SELECT a.isrunning,
w.worktype,
cnt = count(*)
FROM dbo.asset a WITH (NOLOCK)
INNER JOIN dbo workorder w WITH (NOLOCK) on w.assetnum = a.assetnum
WHERE a.assetnum IN ('list', 'of', 'asset', 'numbers')
This would give you a count of worktypes for each asset and might allow the database server to optimize more efficiently. Also consider adding indices or using a temp table as other answers have suggested.

Getting most recent record based on datetime column SQL

I am trying to select the most recent record. Right now it is returning all records. Which makes since, because I have not put in a filter to get most recent, I am unsure of how to do that. Here is my code:
select
c.my_Name, a.my_Num, d.myBrand, a.order_bill, a.myDate
from
[table1] a
left join
[table2] b on a.[myCode] = b.[myCode]
left join
[table3] c on c.myTag = b.myTag
left join
[table4] d on a.[myHash] = d.[myHash]
where
c.[myName] = 'test name'
I am wanting to get most recent record from the table, I am guessing the most efficient way is to get most recent a.myDate.
I'd write
SELECT TOP 1
c.my_Name, a.my_Num, d.myBrand, a.order_bill, CONVERT(char(10), a.myDate,126)
FROM [table1] a
LEFT JOIN [table2] b on a.[myCode] = b.[myCode]
LEFT JOIN [table3] c on c.myTag=b.myTag
LEFT JOIN [table4] d on a.[myHash] = d.[myHash]
WHERE c.[myName] = 'test name'
ORDER BY a.myDate DESC
Something like this might help
select c.my_Name, a.my_Num, d.myBrand, a.order_bill, MAX(a.myDate)
from [table1] a
left join [table2] b on a.[myCode] = b.[myCode]
left join [table3] c on c.myTag=b.myTag
left join [table4] d on a.[myHash] = d.[myHash]
where c.[myName] = 'test name'
group by c.my_Name, a.my_Num, d.myBrand, a.order_bill
order by a.myDate DESC
This will grab distinct records with the greatest (most recent) a.myDate, grouped by your other elements.
Be aware of duplicates. Use your duplicate criteria keys in the select statement, or whatever elements you absolutely need to be distinct.

Syntax error (missing operator) in query with parenthesized FROM clause

I am working with asp.NET and C# with an access database to create a web application.
My current issue is with an SQL statement. In the project i have already successfully used a string value to build and store a query. Because it is stored in a string it is a bit ugly to look at. The problem is with this last query i am writing. It has 2 inner joins in it and i am unsure what exactly is wrong.
The error i get is a syntax error (missing operator) and it then lists everything inside the parenthesis. Here is the query:
SELECT Employee.[First Name], Employee.[Last Name], Employee.[Email],
Departments.[Department]
FROM (
Employee INNER JOIN EmpDept ON Employee.[EmpUserName] = EmpDept.[EmpUserName]
INNER JOIN Departments ON Departments.[Department Number] = '2'
)
WHERE Departments.[Campus]='Clarion';
It is very ugly like this, i know.. Im hoping that since this is a syntax error it wont be too hard.
This query is designed to return the name, email, and department of an employee. The 2 is given with c# code and is determined earlier in the code, but it stands for a certain department. The empDept table goes between the Departments table and the employee table so an employee can be in more than one department.
Any help is greatly appreciated. Thanks
Just remove the parenthesis. They force the database to try to treat the entire expression as a single table, which isn't right.
Also, based on your description, I'd write the query to match the department in the join with what's in the EmpDept table, and then use the WHERE clause to filter down to dept '2'. Right now you filter the Department table down to department '2', but leave it unconditionally related to the rest of the query. This means you're pulling in Employee records from any department.
Finally, I consider it a good practice to get in the habit of using table aliases. Not only does it make your code shorter, but more advanced queries will often pull from more than one instance of the same table, and the aliases make it explicit which instance of the table you mean.
SELECT e.[First Name], e.[Last Name], e.[Email], d.[Department]
FROM Employee e
INNER JOIN EmpDept ed ON e.[EmpUserName] = ed.[EmpUserName]
INNER JOIN Departments d ON d.[Department Number] = ed.[Deptartment Number]
WHERE d.[Campus]='Clarion' AND d.[Department Number] = '2';
Try this
SELECT Employee.[First Name], Employee.[Last Name],
Employee.[Email], Departments.[Department]
FROM Employee
INNER JOIN EmpDept ON Employee.[EmpUserName] = EmpDept.[EmpUserName]
INNER JOIN Departments ON EmpDept.[DepartmentId] = Departments.[Id]
WHERE Departments.[Campus]='Clarion'
AND Departments.[Department Number] = '2'
You'll need an ID on the EmpDept table that matches the Departments table.
SELECT Employee.[First Name], Employee.[Last Name], Employee.[Email], Departments.[Department]
FROM Employee
INNER JOIN EmpDept ON Employee.[EmpUserName] = EmpDept.[EmpUserName]
INNER JOIN Departments ON Departments.[Department Number] = Employee.[Department Number]
WHERE Departments.[Campus]='Clarion' and Departments.[Department Number]=2
There is a small syntax error in squery, it better to join tables with column name and mention column value condition in where clause..
Access requires parentheses within the FROM clause if it includes more than one join. As a first step, try a query like this in the Access query designer.
SELECT
Employee.[First Name],
Employee.[Last Name],
Employee.[Email],
Departments.[Department]
FROM
(Employee
INNER JOIN EmpDept
ON Employee.[EmpUserName] = EmpDept.[EmpUserName])
INNER JOIN Departments
ON Departments.[Department Number] = '2'
WHERE Departments.[Campus]='Clarion';
I think I placed the parentheses correctly; you can confirm in the query designer. However, I'm puzzled by the second ON clause.
ON Departments.[Department Number] = '2'
That clause doesn't reference any field from the "left" side of the join. I don't understand what it's supposed to accomplish, and I'm unsure whether the db engine will do what you want there.
Try this:
SELECT Employee.[First Name], Employee.[Last Name], Employee.[Email],
Departments.[Department]
FROM Employee
INNER JOIN EmpDept ON Employee.[EmpUserName] = EmpDept.[EmpUserName]
INNER JOIN Departments ON EmpDept.[Department Number] = Departments.[Department Number]
/* Or whatever your foreign key between Departments and EmpDept is */
WHERE Departments.[Department Number] = '2'
AND Departments.[Campus] = 'Clarion'
If you have your heart set on a subquery, you need to alias it and make sure it forms a complete query on its own:
SELECT e.[First Name], e.[Last Name], e.Email, e.Department
FROM
(
SELECT Employee.[First Name], Employee.[Last Name], Employee.[Email],
Departments.[Department], Departments.Campus
FROM Employee
INNER JOIN EmpDept ON Employee.[EmpUserName] = EmpDept.[EmpUserName]
INNER JOIN Departments ON EmpDept.[Department Number] = Departments.[Department Number]
AND Departments.[Department Number] = '2'
) AS e
WHERE e.Campus = 'Clarion'

Reduce Execution Time in MYSQL from ASP.NET

i have a table which is relevant GPS application in mysql. whenever i am executing from asp.net application it showing fetal error. so i have decided to run in mysql, it will take more than 1 min(exactly 70 sec) for executing the SP. is it possible to sort out the issues.
Further information:
table 1 : server_gpsdata(it contains gps data. it locks every 10 secs from gps device).
select * from server_gpsdata SD
INNER JOIN mstcab MC on MC.cabid= SD.cabid
INNER JOIN server_tblstatus TS on TS.statusid= MC.CabStatusid
INNER JOIN carmaster CM on CM.carid= MC.carid
INNER JOIN cabtype CT on CT.cabtypeid= CM.sizeid
where date(SD.cur_datetime) =current_date and
MC.Cabid not in (select D.cabid from trncabdriver D
where date(D.logintime)=current_date) and
SD.gpsdataid in (select max(SGD.gpsdataid) from server_gpsdata SGD
where date(SGD.cur_datetime)=current_date
group by SGD.cabid);
The following should show a significant improvement in performance:
select SD.*, MC.*, TS.*, CM.*, CT.* from
(select max(SGD.gpsdataid) maxgpsdataid from server_gpsdata SGD
where date(SGD.cur_datetime)=current_date
group by SGD.cabid) SDM
INNER JOIN server_gpsdata SD ON SDM.maxgpsdataid = SD.gpsdataid
INNER JOIN mstcab MC on MC.cabid= SD.cabid
INNER JOIN server_tblstatus TS on TS.statusid= MC.CabStatusid
INNER JOIN carmaster CM on CM.carid= MC.carid
INNER JOIN cabtype CT on CT.cabtypeid= CM.sizeid
LEFT JOIN trncabdriver D ON MC.Cabid= D.Cabid AND date(D.logintime)=current_date
where D.Cabid IS NULL
Note that both the existing and proposed queries are returning all columns from the server_gpsdata, mstcab, server_tblstatus, carmaster and cabtype tables - the query is likely to perform better if only the columns that are actually required are selected in the query.

Categories