How to optimze lookup table? - tsql

I am developing a TSQL query using SSMS 2008 R2 and I want to optimize this sproc that currently uses many left joins. There is a lookup table that contains one row / lookup value. So my TSQL code looks like this:
Table A = main record table
Table B = Lookup Table
row1 x unique_identifier, y varchar(100)
row2 x unique_identifier, y varchar(100)
row3 x unique_identifier, y varchar(100)
row4 x unique_identifier, y varchar(100)
so each row in this lookup table has two values: one unique_identifier and the other value is a varchar. And so currently my sproc code looks like:
select *
FROM A
LEFT JOIN B ON B.X = A.X WHERE B.X = 123456
LEFT JOIN B2 ON B2.X = A.X WHERE B2.X = 123457
LEFT JOIN B3 ON B3.X = A.X WHERE B3.X = 123458
LEFT JOIN B4 ON B4.X = A.X WHERE B4.X = 123459
LEFT JOIN B5 ON B5.X = A.X WHERE B5.X = 123451
I'm sure there must be a more efficient way to do this though. And my real sproc code actually joins this lookup table 30 times instead of 5 times. I have also tried using a temp table but that didn't seem to optimize it either. Any recommendations for how to replace all of the LEFT JOINs?
OK, so I am updating this question now. This is my exact query:
SELECT DISTINCT
lut.[description] as UDT_Injuries,
lut2.[description] as abduction,
lut3.[description] as ARREST_PARENT
FROM evolv_cs.dbo.incident_header_x x with (nolock)
LEFT JOIN user_defined_lut_rv lut on lut.user_defined_lut_id = x.UDT_Injuries
LEFT JOIN user_defined_lut_rv lut2 on lut2.user_defined_lut_id = x.ABDUCTION
LEFT JOIN user_defined_lut_rv lut3 on lut3.user_defined_lut_id = x.ARREST_PARENT
WHERE lut.[description] IS NOT NULL OR lut2.[description] IS NOT NULL OR lut3.[description] IS NOT NULL
and the first 10 rows of output for this query:
UDT_Injuries abduction ARREST_PARENT
NULL NULL Outside of facility
Client NULL NULL
Client NULL Outside of facility
None NULL NULL
None NULL Outside of facility
Other adult NULL NULL
Other adult NULL Outside of facility
Parent NULL NULL
Peer NULL NULL
Sibling NULL NULL
FYI, I looked at the article on PIVOT and UNPIVOT, but I do not want to aggregate any data. Instead I want to translate key id values from incident_header_x into varchar values from user_defined_lut_rv.
Sample data from incident_header_x looks like:
UDT_Injuries ABDUCTION ARREST_PARENT
5B84773B-99BF-4EB9-8545-EFC06A35FE29 NULL NULL
NULL 4F18EDE9-BBBA-4430-9EF4-4E28EAC1E6D4 NULL
5B84773B-99BF-4EB9-8545-EFC06A35FE29 NULL NULL
NULL NULL 4F18EDE9-BBBA-4430-9EF4-4E28EAC1E6D4
NULL NULL 5B84773B-99BF-4EB9-8545-EFC06A35FE29
Does this make sense now what I am trying to achieve? To translate these id values into varchar values from the user_defined_lut_rv lookup table?

In short, no - there is no more efficient or different way to do this. Are you having performance issues, or are you finding the the code unwieldy?
Anyway you may wish to do some research on 'the one true lookup table', which this looks similar (not identical) to, to get some ideas of disadvantages and advantages in this design.

As the join condition is always the same, it seems you are looking for a pivot: http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
If this is not what you are looking for, please provide more details. Example data and expected results would be a great start.

Related

How to return different format of records from a single PL/pgSQL function?

I am a frontend developer but I started to write backend stuff. I have spent quite some amount of time trying to figure out how to solve this. I really need some help.
Here are the simplified definitions and relations of two tables:
Relationship between tables
CREATE TABLE IF NOT EXISTS items (
item_id uuid NOT NULL DEFAULT gen_random_uuid() ,
parent_id uuid DEFAULT NULL ,
parent_table parent_tables NOT NULL
);
CREATE TABLE IF NOT EXISTS collections (
collection_id uuid NOT NULL DEFAULT gen_random_uuid() ,
parent_id uuid DEFAULT NULL
);
Our product is an online document collaboration tool, page can have nested pages.
I have a piece of PostgreSQL code for getting all of its ancestor records for given item_ids.
WITH RECURSIVE ancestors AS (
SELECT *
FROM items
WHERE item_id in ( ${itemIds} )
UNION
SELECT i.*
FROM items i
INNER JOIN ancestors a ON a.parent_id = i.item_id
)
SELECT * FROM ancestors
It works fine for nesting regular pages, But if I am going to support nesting collection pages, which means some items' parent_id might refer to "collection" table's collection_id, this code will not work anymore. According to my limited experience, I don't think pure SQL code can solve it. I think writing a PL/pgSQL function might be a solution, but I need to get all ancestor records to given itemIds, which means returning a mix of items and collections records.
So how to return different format of records from a single PL/pgSQL function? I did some research but haven't found any example.
You can make it work by returning a superset as row: comprised of item and collection. One of both will be NULL for each result row.
WITH RECURSIVE ancestors AS (
SELECT 0 AS lvl, i.parent_id, i.parent_table, i AS _item, NULL::collections AS _coll
FROM items i
WHERE item_id IN ( ${itemIds} )
UNION ALL -- !
SELECT lvl + 1, COALESCE(i.parent_id, c.parent_id), COALESCE(i.parent_table, 'i'), i, c
FROM ancestors a
LEFT JOIN items i ON a.parent_table = 'i' AND i.item_id = a.parent_id
LEFT JOIN collections c ON a.parent_table = 'c' AND c.collection_id = a.parent_id
WHERE a.parent_id IS NOT NULL
)
SELECT lvl, _item, _coll
FROM ancestors
-- ORDER BY ?
db<>fiddle here
UNION ALL, not UNION.
Assuming a collection's parent is always an item, while an item can go either way.
We need LEFT JOIN on both potential parent tables to stay in the race.
I added an optional lvl to keep track of the level of hierarchy.
About decomposing row types:
Combine postgres function with query
Record returned from function has columns concatenated

Joining one table twice in postgresql

I have two columns in the same table that I want to join in Postgresql but for some reason I’m getting this error. Don’t know how to figure it out. Please help.
[42P01] ERROR: relation "a" does not exist
Position: 10
X table contains two pools(ABC,XYZ), ids, numbers and description. If an ID exists in one pool but not in the other, it should update description column to “ADD”. Pools need to be joined on number.
UPDATE A
SET A.Description = 'ADD'
FROM X AS A
LEFT JOIN X AS B ON B.number = A.number
AND B.id = 'ABC'
WHERE A.id = 'XYZ'
AND B.number IS NULL
AND A.Description IS NULL;
With standard SQL you can't do a join as part of an update, but what you can do is include a subquery to select the id's to update. The subquery can contain a join. I'm not entirely clear on what you're actually trying to accomplish, but you could do something like this:
UPDATE x SET description='ADD' WHERE number IN (
SELECT a.number FROM x AS a
LEFT OUTER JOIN x AS b ON a.number=b.number AND a.id='XYZ' AND b.id='ABC'
WHERE b.number IS NULL
);
This will join the table x with itself and will select (and update) any numbers's that don't have a matching number in the 'ABC' and 'XYZ' zone.
PostgreSQL does have a UPDATE FROM syntax that does let you update with complex subqueries. It's more flexible but it's non-standard. You can find an example of this type of query here.

What does a column assignment using an aggregate in the columns area of a select do?

I'm trying to decipher another programmer's code who is long-gone, and I came across a select statement in a stored procedure that looks like this (simplified) example:
SELECT #Table2.Col1, Table2.Col2, Table2.Col3, MysteryColumn = CASE WHEN y.Col3 IS NOT NULL THEN #Table2.MysteryColumn - y.Col3 ELSE #Table2.MysteryColumn END
INTO #Table1
FROM #Table2
LEFT OUTER JOIN (
SELECT Table3.Col1, Table3.Col2, Col3 = SUM(#Table3.Col3)
FROM Table3
INNER JOIN #Table4 ON Table4.Col1 = Table3.Col1 AND Table4.Col2 = Table3.Col2
GROUP BY Table3.Col1, Table3.Col2
) AS y ON #Table2.Col1 = y.Col1 AND #Table2.Col2 = y.Col2
WHERE #Table2.Col2 < #EnteredValue
My question, what does the fourth column of the primary selection do? does it produce a boolean value checking to see if the values are equal? or does it set the #Table2.MysteryColumn equal to some value and then inserts it into #Table1? Or does it just update the #Table2.MysteryColumn and not output a value into #Table1?
This same thing seems to happen inside of the sub-query on the third column, and I am equally at a loss as to what that does as well.
MysteryColumn = gives the expression a name also called a column alias. The fact that a column in the table#2 also has the same name is besides the point.
Since it uses INTO syntax it also gives the column its name in the resulting temporary table. See the SELECT CLAUSE and note | column_alias = expression and the INTO CLAUSE

SQL Insert values with subquery and column multiplication

I am trying to insert a value with a subquery including a column multiplication into a table. This works perfectly, however if I query the table, it only has 0 values. Does anybody know why?
My queries are:
create table user_payments
(payment_stream number(4));
insert into user_payments (payment_stream)
select ct.min_price*s.stream_min as payment_stream
from users u
, streaming s
, content_type ct
, contract c
, media_content mc
where u.user_ID = s.user_ID
and mc.media_content_ID = s.media_content_ID
and ct.content_type_ID = mc.content_type_ID
and u.user_ID = c.user_ID
and c.contract_name = 'Pay as you go';
If I query the select query individually, I get the expected outcome, however, once the rows are inserted into the table, all values are 0.
Thanks for your help!
try datatype numeric(18,2) in table var

sql compare two table for different select

I have this two table
One:
ID SystemProductID
E57AD213-3953-481C-BA2B-4AF8B98A87B6 02188530
2471F038-2646-4EC2-B245-4AF919901A71 02000099
3A7D0896-EBB3-4E30-A535-4AF94FE83CCE 02025567
Two:
SystemProductID
02188530
02000099
02460103
02460101
How to select some of that
IsExist SystemProductID ID
true 02188530 E57AD213-3953-481C-BA2B-4AF8B98A87B6
true 02000099 2471F038-2646-4EC2-B245-4AF919901A71
false 02460103 NULL
false 02460101 NULL
Please tell me how to do this
full join is not working on what i want
In my way of thinking, I always use what tables I know will have all of the rows of data and LEFT JOIN from there. I generally don't like RIGHT JOINs as they seem counter-intuitive to me. A FULL JOIN could work as well.
So, we take all the table two's rows and left join on the ID for table one where we can.
SELECT
CASE
WHEN t1.SystemProductID IS NULL THEN 'false'
else 'true'
END [IsExist]
,t2.SystemProductID
,t2.ID
FROM TableTwo t2
LEFT JOIN TableOne t1 ON t1.SystemProductID=t2.SystemProductID