Can someone please share with me a good approach on how to build a query that uses one text box with multiple keywords that pick columns on several DB tables. Please see attached screen shot.
Requirement
I will need to define a format rule so the user "must" enter an input search with the following format: [category], [suburb] [postcode]. The code behind logic (web API) can then parse this input (this is where my search query will be parsed).
If you expect unified output then you can use UNION
INSERT INTO #resultTable
SELECT serviceid
FROM (
SELECT DISTINCT serviceid
FROM addresses s
WHERE s.suburb = #criteria
OR s.postal = #criteria
UNION
SELECT DISTINCT serviceid
FROM categories c
WHERE c.categotyName = #criteria
)
SELECT *
FROM services s INNER JOIN #resultTable ON ...
Related
We are using GraphQL Dotnet in a dotnet core 5.0 API.
We have a relational data structure like this
Organisation --> (Zero or many) Employers --> (Zero or many) Departments.
In an attempt to optimise our database queries we are doing some parsing of the query and hoping to limit the fields returned by SQL using dynamic linq.
They have some pretty basic examples like this
var resultDynamic = context.Customers
.Select("new { City, CompanyName }")
.ToDynamicList();
So you can select Customers.City, and Customers.CompanyName to a new dynamic object list.
This is not far off what we want to do, however, some of the properties we want to query are nested in collections.
for instance the following graphQL query
organisations {
id,
name,
employers {
addressLine1
}
}
}
Should return a list of organisations with id and name populated, and their employers with only the addressline1 populated.
If our query is Database.Organisations.Include(x => x.Employers); graphql parses this fine, and we return the correct information. However, if you inspect the SQL, it's getting every field for organisation, and every field for employers, and GQL is basically trimming the data client side.
Using dynamic linq I can do this
Database.Organisations.Select("new Organisation {id, name}");
and it works great, returns the organisation with id and name populated, and those are the only SQL fields in the SQL select statement.
But as soon as I try to Select the addressLine1 field of employers I hit a bit of a brick wall.
I can do this
Database.Organisatons.Select("new Organisation {id, name, employers}");
and it will only select the required fields from organisations, but all employer fields are selected (and GQL does the trimming client side) but I can't figure out a way to do employers.addressLine1 so that the subquery in sql only selects the one field.
Trying things like Organisations.Select("new Organisation {id, name, employers.name}"); just results in
No property or field 'name' exists in type 'List`1'
Which is obviously because I Employers is a List property and I am basically trying to get that (List).Name ... which doesn't exist.
Ideally I want to do this in this string based select format as i can build that up by parsing the GraphQL query and then I could only select the fields required from the child objects, but I have no idea what the format of that would be and can't find any examples.
It should be possible with employers.Select(name).
Example in LinqPad:
void Main()
{
Rooms.Dump();
(Rooms.Where(r => r.Id == 3) as IQueryable).Select("new { name, RoomReservations.Select(CheckinDate) as CheckinDates }").Dump();
}
Results into:
And the generated SQL looks like (only the 'name' and the 'CheckinDate' are selected in the query):
-- Region Parameters
DECLARE #p0 Int = 3
-- EndRegion
SELECT [t0].[Name], [t1].[CheckinDate], (
SELECT COUNT(*)
FROM [Reservations] AS [t2]
WHERE [t2].[RoomId] = [t0].[Id]
) AS [value]
FROM [Rooms] AS [t0]
LEFT OUTER JOIN [Reservations] AS [t1] ON [t1].[RoomId] = [t0].[Id]
WHERE [t0].[Id] = #p0
ORDER BY [t0].[Id], [t1].[Id]
--> Note that I tried to make a GraphQL library which uses DynamicLinq, however not all logic is supported. You can take a look here:
https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq
I am trying to create a query to help get a list of accounts from an existing database. I will have two lists of integers passed in through two Table Value Parameters(TVP) from C#. I then need to see if multiple columns have any of the values in the corresponding TVP tables. The TVP lists of integers are provided by different clients and may differ between clients. That is why they are TVP's to allow the values to be passed in as parameters.
The data structure cannot be changed, it is created based on data from another system. Comments about changing the data structure won't be helpful. To help I will talk about an example table that would help show what I need.
Looking at a table like the following:
Table Accounts
varchar(200) AccountId
int StatusId1
int StatusId2
int StatusId3
int StatusId4
int Identifier1
int Identifier2
int Identifier3
int Identifier4
int Identifier5
I know that I can do a sql statement like:
Select AccountId from Accounts where StatusId1 In (1,2,3)
I was able to learn that I can reverse the In command as well:
Select AccountId from Accounts where 1 In (StatusId1, StatusId2, StatusId3, StatusId4)
This only lets me check one value against each column. The problem is I need to mix the two while using the TVP for the list of integers.
The closest I have been able to create is the following:
--Load the TVP lists
SELECT * INTO #StatusCodes FROM #StatusId
SELECT * INTO #IdentityCodes FROM #IdentifierId
--Find the Accounts that have the chosen Ids
SELECT AccountId
FROM Accounts
WHERE StatusId1 IN( SELECT Id FROM #StatusCodes)
OR StatusId2 IN( SELECT Id FROM #StatusCodes)
OR StatusId3 IN( SELECT Id FROM #StatusCodes)
OR StatusId4 IN( SELECT Id FROM #StatusCodes)
OR Identifier1 IN (SELECT Id FROM #IdentityCodes)
OR Identifier2 IN (SELECT Id FROM #IdentityCodes)
OR Identifier3 IN (SELECT Id FROM #IdentityCodes)
OR Identifier4 IN (SELECT Id FROM #IdentityCodes)
OR Identifier5 IN (SELECT Id FROM #IdentityCodes)
This query worked in my prototype and I got back the list of accounts that had at least one of these ids. I see a lot of select statements and it doesn't look very good. I am not sure how well it performs either. I am wondering if there is a better way to do this?
This is for a system that creates a report based on conditions our clients make. Each client runs from a couple to 100 reports each night. That means this is run possibly hundreds of times each night. While it isn't a system running thousands of times per hour, it does process a lot of data. Some of the databases it will search will be big with lots of accounts to search.
One option uses exists:
select a.acountId
from accounts a
where
exists (
select 1
from #StatusCodes s
where s.id in (a.StatusId1, a.StatusId2, a.StatusId3, a.StatusId4)
)
or exists (
select 1
from #IdentityCodes i
where i.id in (a.Identifier1, a.Identifier2, a.Identifier3, a.Identifier4)
)
I have a c# project where I am using a MS access database, and I am trying to put some items from two (related) tables, in the same listView.
This is the code that I have:
Where it sais "none" is the place where I want to put an item from the other table, but i don't know how. Since they have a relationship I thought that was possible to call items from one table or another.
Please note that I am fairly new to c# and working with databases.
You should join the two tables together to get the unified result.
You could do something like this:
select c.*
, s.otherFieldYouNeed
from ClientsT c
join SomeOtherTable s
on c.someId = s.someId
since the two table are related you can use a join query to get the desired result:
select FirstName,LastName,'none',CellPhone,ClientID from Clients inner join mySecondTable
on Clients.mysharedField=mySecondTable.mysharedField
select FirstName,LastName,(select none from SecondTable where Clients.Field= SecondTable.Field),CellPhone,ClientID from Clients
Try altering your query to include this information. Something like:
Select FirstName, LastName, ColumnFromOtherTable, CellPhone, ClientsT.ClientID
from ClientsT, OtherTable where ClientsT.ClientID=OtherTable.ClientID
Of course, in order to do this, you have to have a corresponding ID field in both tables.
This question is related to both c# and SQL Server.
I want to figure out how to do a custom search.
I have three tables
Customer
CusId, Name, Telephone
Employee
EmpId, Name, Job
Appointment
AppId, Date, EmpId, CusId
My C# form has three checkboxes. I want to find the data according to those checked values.
Ex: when customer,employee,app check boxes have selected, I want to find data on depending on all those three values.
When only two or one is selected I want to search depending on those selection. Here there will be total 6 combinations.
How to write a query to get correct result when I pass those values as parameters to a stored procedure.
Do I have to write 6 stored procedures to get the result?
Are there any methods to do this easily?
Please help me to fix this matter. Thanks in advance.
With a query such as the below (would suggest in a stored proc):
-- Parameters to a SQL sproc
DECLARE #CustID INT, #EmpID INT, #AppointmentID INT
-- Set Parameters here for testing
SELECT *
FROM Appointment as A
INNER JOIN Employee as E
ON E.EmpID = A.EmpId
INNER JOIN Customer as C
ON C.CusID = A.CusID
WHERE (#CustID IS NULL OR C.CUsID = #CustID)
AND (#EmpID IS NULL OR E.EmpID = #EmpID)
AND (#AppointmentID IS NULL OR A.AppID = #AppointmentID)
You then need to pass in the parameters appropriately, either an ID if selected, or null if not filtering on one item.
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.