SQL If-Else logic based on value of one table - sql

I have the following tables:
Production Table
SerialNumber WorkOrderNumber ItemName ItemType
1234 A2234 ASD 1
1234 A2234 ASD-T 2
1111 B2234 ZXC-T 2
WorkOrder Table
WorkOrderNumber ItemName ItemType
B2234 ZXC 1
B2234 ZXC-T 2
B2234 ZXC-C 3
Scenario: User inputs Serial Number, wants to get the item name of itemtype = 1 from either production table or workorder table
Desired Result
User input Serial number 1234 in application:
ItemName : ASD [Found in production table]
User input Serial number 1111 in application:
ItemName : ZXC [Found in workorder table]
Production and Workorder table is heavily simplified for demonstration purposes. The table contains millions of rows each. I need to come up with a performant query to get the item name.
The only solution I have thought of is to do the following
Use stored procedure and write an if-else logic
Check if the item type of the entered serial number is 1. If true, return itemname.
If itemtype is not 1, get the itemname from workorder table with itemtype = 1
But I'm not sure if that's a preferred method for performance and I feel kinda icky about putting business logic in database.
How would one handle this problem elegantly?

Try this:
select top 1 pt.serialNumber,pt.workOrderNumber,
isNull(wt.ItemName,pt.ItemName) as NameToReturn
from prodTable pt
left join worktable wt on pt.WorkOrderNumber=wt.workOrderNumber and wt.itemType=1
where pt.serialNumber = <input>
order by p1.itemType
Not sure I understand all your requirements, but the above should give you a start point. It finds the part in the prodTable and optionally finds a part in the work Item table. The is Null logic assumes that if a type one exists in Work table, it will be used. You might need to tweak this to a case statement if your rules are different (i.e. 1 in prod table should override worktable)

Related

Replacing the IN operator in Power BI RLS

I want to ask if its possible to use something like IN operator in Power BI RLS DAX.
The approach I am using now seems very convoluted to me, and I want to ask if it could be done better and simpler.
I have two types of identifiers in my Fact table: Code and GroupCode. Code is NOT NULL identifier and can have multiple unique GroupCodes and GroupCode can be NULL and can be assigned to multiple Code.
Example Fact table:
Code
GroupCode
Client
1
a
John
1
b
Susie
1
c
Mark
2
a
John
2
NULL
Mary
3
b
Susie
I want to create report where User enters by Code, but see all rows with it GroupCode.
In SQL it would be:
SELECT * FROM table
WHERE GroupCode IN (SELECT GroupCode FROM TABLE WHERE Code = '2') or Code = '2'
For now I created Dictionary table from my Fact table with Code and CodeDict, where CodeDict = ISNULL(GroupCode, Code). Also added CodeDict column to Fact table to create relation based on it, between Dict and Fact tables. Should be (1:*), but it shows (*:*).
Example Dict table:
Code
GroupCode
1
a
1
b
1
c
2
a
2
2
3
b
As for RLS rule it is set on Dict table as [Code] = #USERPRINCIPALNAME().
So for example if User open report using Code = 2. RLS will filter Dict table so CodeDict will be (a, 2) and by them, it will filter Fact table to shows rows with Code=(1, 2)
It's very convoluted approach and I don't like it, but I have no idea I could make it other way. I worry about (*:*) relation and that I have to create Bridge Dict table.
What do you think about this approach to this problem?
Is there a way to implement IN operator in RLS rule?

SQL Query -- IF X is shared between two strings in a primary composite key?

Not sure how to explain this, as I have only basic SQL knowledge. I need help with some logic to signal a user when a unique string is referenced more than once in a composite primary key.
A table I use contains a composite primary key which ties a unique "ItemCode" to a repeating "WarehouseCode". The "QuantityOnHand" column lists how much we have of an item in each warehouse:
_____PK_______
| |
ItemCode | WarehouseCode | QuantityOnHand
---------------------------------------------
001 A 100
001 B 500
002 A 600
003 B 250
etc.
How do I "signal" (create a boolean value?) when ItemCode 001 is in two separate warehouses?
The end result is a crystal report which somehow alerts the user when an item's total quantity is split between two warehouses.
Thanks
Utilise GROUP BY and HAVING. For example this query will return a list of ItemCodes and a count of how many warehouses they are in where that count is greater than 1.
SELECT ItemCode, COUNT(*)
FROM table
GROUP BY ItemCode
HAVING COUNT(*) > 1
In crystal you would probably want to create a group on ItemCode and then you can evaluate: DistinctCount({table.WarehouseCode}) but I would suggest you use SQL group by ItemCode having count(distinct WarehouseCode) > 1
It is much easier to do in Crystal than in pure SQL
Using a Crystal function:
If {table.ItemCode} = Previous({table.ItemCode})
Then //we have a duplicate ItemCode, do something to flag it
The above assumes that the details have these values and that they were not grouped. Although, even if they were grouped something like this should do it
If {table.ItemCode} = Previous({table.ItemCode})
and {table.WarehouseCode} <> Previous({table.WarehouseCode})
Then //we have a duplicate ItemCode

Fetch a single field from DB table into itab

I want to fetch the a field say excep_point from a transparent table z_accounts for the combination of company_code and account_number. How can I do this in ABAP SQL?
Assume that table structure is
|company_code | account_number | excep_point |
Assuming you have the full primary key...
data: gv_excep_point type zaccounts-excep_point.
select single excep_point
into gv_excep_point
from zaccounts
where company_code = some_company_code
and account_number = some_account_number.
if you don't have the full PK and there could be multiple values for excep_point
data: gt_excep_points type table of zaccounts-excep_point.
select excep_point
into table gt_excep_points
from zaccounts
where company_code = some_company_code
and account_number = some_account_number.
There is at least another variation, but those are 2 I use most often.
For information only. When you selects data into table you can write complex expressions to combine different fields. For example, you have internal table (itab) with two fields "A" and "B". And you are going to select data from DB table (dbtab) wich have 6 columns - "z","x","y","u","v","w". And for example each field is type char2 You aim to cimbine "z","x","y","u" in "A" field of internal table and "v","w" in "B" field. You can write simple code:
select z as A+0(2)
x as A+2(2)
y as A+4(2)
u as A+6(2)
v as B+0(2)
w as B+2(2) FROM dbtab
INTO CORRESPONDING FIELDS OF TABLE itab
WHERE <where condition>.
This simple code makes you job done very simple
In addition to Bryans answer, here is the official online documentation about Open SQL.

Dynamic columns when pivoting

I have a table of equipment, a table of customers and a sparse table of equipment and customers. I want to produce a query that returns a 1 if the equipment/Customer table record exists and a 0 if it doesn't for each customer. There are only a small number of customers in this problem, so what I want back should look like this:
EquipmentID Cust1 Cust2 Cust3
----------- ----- ----- -----
1234 1 0 1
1357 0 1 0
2234 1 0 0
I can use a cross join to get a master list of possible records, but that returns the information in rows. I want to see it in columns, but the PIVOT keyword requires that I name the columns first. What I need is for the column names (Cust1, Cust2...) to be dynamic.
If you want to do that, then you have to create the query string dynamically and then pass it to the sp_execute stored procedure. AFAIK, there isn't a way to do it without constructing the query string dynamically.
If you have a reporting tool handy use your current query and make a "martix", "cross-tab", or "pivot table" report.

SQL Precedence Query

I have a logging table which has three columns. One column is a unique identifier, One Column is called "Name" and the other is "Status".
Values in the Name column can repeat so that you might see Name "Joe" in multiple rows. Name "Joe" might have a row with a status "open", another row with a status "closed", another with "waiting" and maybe one for "hold". I would like to, using a defined precedence in this highest to lowest order:("Closed","Hold","Waiting" and "Open") pull the highest ranking row for each Name and ignore the others. Anyone know a simple way to do this?
BTW, not every Name will have all status representations, so "Joe" might only have a row for "waiting" and "hold", or maybe just "waiting".
I would create a second table named something like "Status_Precedence", with rows like:
Status | Order
---------------
Closed | 1
Hold | 2
Waiting | 3
Open | 4
In your query of the other table, do a join to this table (on Status_Precedence.Status) and then you can ORDER BY Status_Precedence.Order.
If you don't want to create another table, you can assign numeric precedence using a SELECT CASE
Select Name, Status, Case Status
When 'Closed' then 1
When 'Hold' then 2
When 'Waiting' then 3
When 'Open' Then 4
END
as StatusID
From Logging
Order By StatusId -- Order based on Case
A lookup table is also a good solution though.
I ended up using matt b's solution and using this final query to filter out the lower ranked (lower bing higher numbered).
SELECT * from [TABLE] tb
LEFT JOIN Status_Precedence sp ON tb.Status = sp.Status
WHERE sp.Rank = (SELECT MIN(sp2.rank)
FROM[Table] tb2
LEFT JOIN Status_Precedence sp2 ON tb2.Status = sp2.Status
WHERE tb.Status = tb2.Status)
order by tb.[name]