Transact SQL and Where Statement and CASE Statement - sql-server

I have the following requirement that will multiple joins - Currently this search looks at the client’s residence county. This needs to be changed to look at tbl_client_insurance.region_id for the active, effective insurance for the consumer. If the client has multiple insurances meeting this criteria, use the county for ins_id = 2 (Medicaid). I believe I have most of the query correct, but I am getting hung up on the ti.ins_id, which I believe I will need a case, basically returning only the 2 or else if 2 does not exist return the insurance the client does have.
SELECT
ti.client_id, ti.exp_dt, ins_id, *
FROM
tbl_Client AS tc
INNER JOIN
tbl_client_insurance AS ti ON ti.client_ID = tc.client_ID
WHERE
tc.client_id = 26
AND tc.active = 1
AND (ti.exp_dt >= GETDATE() OR ti.exp_dt IS NULL)
CASE
--- Need some help here.

You may be able to add such a condition to your join logic as
INNER JOIN tbl_client_insurance AS ti ON ti.client_ID = tc.client_ID AND ti.ins_id=2

I don't know what your desired result set is.
Based on your sample you want all matching client insurances.
But it seems you may want just one for that client.
If you just want one for that client, this is just an ordering issue.
You should use a UNION ALL.
The first part is the query for insurance id 2.
The second part is the query for all other insurances.
Order by a new column you provide.
For the first part the new column will be A.
For the second part it will be B.
Then take only the top 1 row.
That way if id 2 exists it will be first, otherwise it will be one of the other insurances, or if there are no matching insurances you will get an empty result set.
The question then becomes how do you tell which of the other insurances to select if there is no medicaid. Again this is just ordering.

Related

SQL query based on list from another query

I am trying to build a query that will generate a list of records based on the results of a very similar query.
Here are the details and examples
Query 1: Generate a list if part #'s in a specific location of the warehouse.
Query 2: Use the list of part #'s generated in #1 to show all locations for the list of part #'s, assuming they will be in both the location specified in #1 and other locations.
Query 1 looks like this:
Select
ItemMaster.ItemNo, BinInfo.BIN, ItemDetail.Qty, ItemDetail.Whouse_ID
From
((ItemDetail
Left Join
ItemMaster on ItemMaster.ID=ItemDetail.Item_ID)
Left Join
BinInfo on BinInfo.ID = ItemDetail.Bin_ID)
Where
ItemDetail.Whouse_ID = '1'
And BinInfo.Bin = 'VLM';
Query 2 needs to be almost identical except the ItemMaster.ItemNo list will come from query #1.
Any help here would be great. I don't know if I need to learn Unions, Nested Queries, or what.
make sure that your first query returns the list of ids that you need.
then write the second query with the WHERE id IN (...) syntax:
SELECT * FROM table1 WHERE id IN
(SELECT id FROM table2 WHERE...) -- first query

SQL-Server join issue when filtering on a freetext (vchar) column

I am stuck with a SQL Server view I am trying to create. The view returns a list of resources that are assigned to a project along with a few other details such as contract information.
I'm having issues with the resource_contracts table though because I'm stuck dealing with what is essentially a free-text field.
SELECT DISTINCT
CONCAT(RTRIM(res.first_name),' ', RTRIM(res.surname)) AS fullname ,
res.main_res_id ,
res.resource_id ,
res.resource_typ ,
res.status ,
rel.rel_value ,
asn.booking_project AS project ,
asn.booking_project_descr AS project_descr ,
asn.assignment_position AS position ,
asn.date_from AS commencement_date ,
DATEADD(DAY,1,asn.date_to) AS end_date ,
con.comment_fx
FROM resourcees res
INNER JOIN resource_relations rel
ON
res.main_res_id = rel.resource_id
AND rel.date_to >= CAST(CURRENT_TIMESTAMP AS DATE)
AND res.client = rel.client
LEFT OUTER JOIN resource_relations cc
ON
res.client = cc.client
AND res.resource_id = cc.resource_id
AND cc.rel_attr_id = 'C1'
AND res.date_to BETWEEN cc.date_from AND cc.date_to
AND cc.status = 'N'
INNER JOIN relation_values ar2
ON
cc.rel_value = ar2.dim_value
AND ar2.client = res.client
INNER JOIN assignments asn
ON
res.main_res_id = asn.resource_id
LEFT OUTER JOIN resource_contracts con
ON
con.dim_value = res.main_res_id
AND res.client = con.client
AND con.comment_fx LIKE '%CONAU%'
AND con.date_to_fx >= asn.date_to
WHERE
asn.booking_project = '123456'
ORDER BY
fullname
I guess the above looks fairly large. It's the last join causing the issue for reference.
The resource_contracts table contacts three columns. I hate this setup, but it's outside of my control unfortunately.
date_from_fx = DATETIME
date_to_fx = DATETIME
comment_fx = VCHAR 255
It's used to record contracts date from and date to, and a free text field that could contain anything annoyingly. Sample values might be "CONAU SPP" or "CONSG ABC" etc..
I'm stuck on the comment_fx field above however.
I specifically want to see contracts containing CONAU, or return a NULL value if they do not have one that meets the date require, or do not have a row at all. Unfortunately this logic is getting mixed up any other contract they have such as "CONSG ABC"
No matter what join I apply, I either can see all the resources with the contract required, or duplicate rows with null values and a mix of the non-applicable contracts. I guess I am missing something simple
Ultimately I need to produce a list of resources that are assigned to a project, but do not have the required contract (CONAU), that list will trigger another process that I've already sorted out.
Updated:
Let me show you the data that gets returned if we removed the resource_contracts table causing my issues:
Data result
Apologies, I couldn't format the table into something that resembled a table to paste here.
Here is the data from the contracts table:
contracts table
There's kind of multiple things I want to do here but I'll simplify it into a single one.
I'm trying to send a parameter to the query, 'CONAU' for example. So it will return all resources that do NOT have a valid row containing the string CONAU.
Problem is, they might have other rows like CONSG, or no rows at all.
During my attempts I would often get the wrong rows to show or when using ISNULL in the SELECT part, I would get null rows and duplicated data.
The conditions could be inverted but I'm trying to learn this myself.
SQL fiddle too: http://sqlfiddle.com/#!18/7558f/2
WHERE
asn.booking_project = '123456'
AND con.comment_fx LIKE '%CONAU%'
To the trailing end.

Multi join issue

*EDIT** Thanks for all the input, and sorry for late reply. I have been away during the weekend without access to internet. I realized from the answers that I needed to provide more information, so people could understand the problem more throughly so here it comes:
I am migrating an old database design to a new design. The old one is a mess and very confusing ( I haven't been involved in the old design ). I've attached a picture of the relevent part of the old design below:
The table called Item will exist in the new design as well, and it got all columns that I need in the new design as well except one and it is here my problem begin. I need the column which I named 'neededProp' to be associated( with associated I mean like a column in the new Item table in the new design) with each new migrated row from Item.
So for a particular eid in table Environment there can be n entries in table Item. The "corresponding" set exists in table Room. The only way to know which rows that are associated in Item and Room are with the help of the columns "itemId" and "objectId" in the respective table. So for example for a particular eid there might be 100 entries in Item and Room and their "itemId" and "objectId" can be values from 1 to 100, so that column is only unique for a particular eid ( or baseSeq which it is called in table BaseFile).
Basically you can say that the tables Environment and BaseFile reminds of each other and the tables Item and Room reminds of each other. The difference is that some tables lack some columns and other may have some extra. I have no idea why it is designed like this from the beginning.
My question is if someone can help me with creating a query so that I can be able to find out the proper "neededProp" for each row in the Item-table so I can get that data into the new design?
*OLD-PART**This might be a trivial question but I can't get it to work as I want. I want to join a few tables as in the sql-statement below. If I start like this and run this query
select * from Environment e
join items ei on e.eid = ei.eid
I get like 400000 rows which is what I want. However if I add one more line so it looks like this:
select * from Environment e
join items ei on e.eid= ei.eid
left join Room r on e.roomnr = r.roomobjectnr
I get an insane amount of rows so there must be some multiplication going on. I want to get the same amount of rows ( like 400000 in this case ) even after joining the third table. Is that possible somehow? Maybe like creating a temporary view with the first 2 rows.
I am using MSSQL server.
So without knowing what data you have in your second query it's very difficult to say exactly how to write this out, and you're likely having a problem where there's an additional column that you are joining to in Rooms that perhaps you have forgotten such as something indicating a facility or hallway perhaps where you have multiple 'Room 1' entries as an example.
However, to answer your question regarding another way to write this out without using a temp table I've crufted up the below as an example of using a common table expression which will only return one record per source row.
;WITH cte_EnvironmentItems AS (
SELECT *
FROM Environment E
INNER JOIN Items I ON I.eid = E.eid
), cte_RankedRoom AS (
SELECT *
,ROW_NUMBER() OVER (ORDER BY R.UpdateDate DESC) [RN]
FROM Room R
)
SELECT *
FROM cte_EnvironmentItems E
LEFT JOIN cte_RankedRoom R ON E.roomnr = R.roomobjectnr
AND R.RN = 1
btw,do you want column from room table.if no then
select * from Environment e
join items ei on e.eid= ei.eid
where e.roomnr in (select r.roomobjectnr from Room r )
else
select * from Environment e
join items ei on e.eid= ei.eid
left join (select distinct roomobjectnr from Room) r on e.roomnr = r.roomobjectnr

SQL HAVING SUM GROUP BY

Using SQL Server 2005. I am building an inventory/purchasing program and I’m at the point where I need the user to “check out” equipment. When he selects a product, I need to query which stock locations have the available Qty, and tell the user which location to walk to/ retrieve product.
Here is a query for a particular [StockLocation_Products].ProductID, with a particular assigned [ProductUsages].ProductUsageID.
SELECT
PROD.ProductID,
PROD.ProductName,
SL.Room,
SL.StockSpace,
SLPPU.ResvQty,
PRDUSG.ProductUsage
FROM [StockLocations] SL
INNER JOIN [StockLocation_Products] SLP ON SL.StockLocationID = SLP.StockLocationID
INNER JOIN [StockLocation_Product_ProductUsages] SLPPU ON SLP.StockLocationID = SLPPU.StockLocationID AND SLP.ProductID = SLPPU.ProductID
INNER JOIN [ProductUsages] PUSG ON SLPPU.ProductUsageID = PRDUSG.ProductUsageID
INNER JOIN [Products] PROD ON SLPPU.ProductID = PROD.ProductID
WHERE SLP.ProductID = 4 AND PRDUSG.ProductUsageID = 1
This query returns:
ProductID ProductName Room StockSpace ResvQty ProductUsage
------------------------------------------------------------------------------------------------------------------------
4 Addonics Pocket DVD+/-R/RW B700 5-D 12 MC Pool
4 Addonics Pocket DVD+/-R/RW B700 6-B 10 MC Pool
4 Addonics Pocket DVD+/-R/RW B700 6-C 21 MC Pool
4 Addonics Pocket DVD+/-R/RW B700 6-D 20 MC Pool
I thought maybe I could use an additional HAVING clause to make this query return which combination of StockSpace(s) you’d need to visit to satisfy a request for some Qty. E.g. User needs to pull 30 of Product (ID =4).
But I don’t really understand how to use GROUP BY with HAVING SUM(), to achieve what I want.
I tried various things in my group by / having clause, but I just don’t get any results.
GROUP BY PROD.ProductID,PROD.ProductName,SL.Room,SL.StockSpace,SLPPU.ResvQty,PUSG.ProductUsage
HAVING SUM(ResvQty) >= 30;
I want results that show (at least one) combination of StockSpaces which sums up to 30, so I can tell the user “you can get 21 units from space ‘6-C’, and 9 units from ‘6-B’. There may be multiple combinations of rows that could sum() >= 30, but I need at least how to find one combination that does! Help!
You can have an inner select, such as:
SELECT count_of_foo, count(bar), baz
FROM (SELECT count(foo) as count_of_foo, bar, baz, other1, other2 FROM complex_query WHERE foo = bar HAVING count(foo) > 1) inner_query
GROUP BY count_of_foo, baz.
This will give you the ability to add more group by after the HAVING clause.
What you are trying to do is a running sum, which you can get with various techniques in SQL. I think the most efficient query, especially if you are trying to do this all in the same query, is to use a CTE (here's one example).
Another technique that doesn't rely on CTE requires the data to be populated into another table (could be a temp table, though) and basically you do a join-and-sort operation as you go.
Once you get the data to include a running sum, then you can simply select the values from which the running sum is less than or equal to the total number that you are trying to locate.
And here is a nice summary of several of the different techniques.

One T-SQL query output to multiple record sets

Don't ask for what, but i need two tables from one SQL query.
Like this...
Select Abc, Dgf from A
and result are two tables
abc
1
1
1
dgf
2
2
2
More details?
Ok lets try.
Now i have sp like this:
SELECT a.* from ActivityView as a with (nolock)
where a.WorkplaceGuid = #WorkplaceGuid
SELECT b.* from ActivityView as a with (nolock)
left join PersonView as b with (nolock) on a.PersonGuid=b.PersonGuid where a.WorkplaceGuid = #WorkplaceGuid
It's cool. But execution time about 22 seconds. I do this because in my programm i have classes that automaticly get data from records set. Class Activity and class Person. That why i can't make it in one recordset. Program didn't parse it.
You can write a stored procedure that has two SELECTs.
SELECT Abc FROM A AS AbcTable;
SELECT Dgf FROM A AS DfgTable;
Depending on your specific requirements, I would consider just submitting two separate queries. I don't see any advantage to combining them.
SQL Server supports legacy COMPUTE BY clause which acts almost like GROUP BY but returns multiple resultsets (the resultsets constituting each group followed by the resultsets with the aggregates):
WITH q AS
(
SELECT 1 AS id
UNION ALL
SELECT 2 AS id
)
SELECT *
FROM q
ORDER BY
id
COMPUTE COUNT(id)
BY id
This, however, is obsolete and is to be removed in the future releases.
Those don't seem to be excessively complicated queries (although select * should in general not be used in production and never when you are doing a join as it needlessly wastes resources sending the value of the joined field twice). Therefore if it is taking 22 seconds, then either you are returning a huge amount of data or you don't have proper indexing.
Have you looked at the execution plans to see what is causing the slowness?

Resources