SQL Server: Update where exists and Insert when not exists - sql-server

I have 2 tables, one is called
INTER and the other one is called COM
The relationship between them is 1:many
Here's the structure of both tables
INTER
NUMBER
ADDRESS
COM
NUMBER
CONTACT
REFERENCE
To give some context about the tables:
The ADDRESS field from the INTER table can be empty (empty string '')
The CONTACT field of the COM table can be of two types: "E-mail" or "Website"
What I'm trying to accomplish is the following:
I want to look at all the records from COM where CONTACT='Website' and insert into COM the values of (INTER.NUMBER,'Website',INTER.ADDRESS)
where INTER.ADDRESS<>'' and INTER.NUMBER does not exist in COM.NUMBER
Otherwise, I want to update the value of COM.REFERENCE, set it to INTER.ADDRESS where COM.CONTACT='Website' and INTER.NUMBER exists in COM.NUMBER and INTER.ADDRESS<>''
How can I accomplish this? I know what the merge statement is but according to the documentation merge does not work well on filtered queries. Also, I know about the exists statement but I don't know how to make this query work.
In case you're wondering, unfortunately, the structure of these tables cannot be modified.
Some sample data:
INTER
ABCD123,google.com
XUEH342,facebook.com
IISI521,twitter.com
IEIEK885,''
COM
ABCD123, Website, test.com
ABCD123,E-mail,bob#gmail.com
XUEH342,Website,facebook.com
XASE456,Website, stackoverflow.com
XASE456,E-mail,tom#gmail.com
After running the query, the results on COM table would look as the following:
ABCD123,Website, google.com
ABCD123,E-mail,bob#gmail.com
XUEH342,Website, facebook.com
IISI521,Website, twitter.com
XASE456,Website, stackoverflow.com
XASE456,E-mail,tom#gmail.com
As you can see, IISI521,twitter.com got inserted,ABCD123,test.com got updated and IEIEK885,'' didn't get inserted because is an empty string.

You can try below query:
MERGE com with (HOLDLOCK) AS cm
USING (SELECT a.number, a.address, b.contact FROM inter a left join com b on a.number = b.number and b.contact = 'website' WHERE a.address != '' ) AS intr
ON cm.number = intr.number and cm.contact = intr.contact
WHEN MATCHED THEN
UPDATE
SET cm.reference = intr.address
WHEN NOT MATCHED THEN
INSERT
(
number,
contact,
reference
)
VALUES
(
intr.number,
'website',
intr.address
);

Related

LEFT join on secure view fails in snowflake

I have a normal view and one secure view and a table.
create or replace NORMALVIEW as select click_id FROM SECURE_VIEW a
LEFT JOIN
TABLE e
ON (e.click_id = a.google_click_id);
select * from NORMALVIEW;
I am getting the error:
SQL execution internal error: Processing aborted due to error 300002:2523989150; incident 8846932.
other operations such as union is working
If you got an incident then you will need to open a case with Snowflake support to understand what is happening.
So I assume the SELECT part is valid:
select e.click_id
FROM SECURE_VIEW a
LEFT JOIN TABLE e
ON (e.click_id = a.google_click_id);
I also assume the view is actually defined more like:
CREATE table test.test.table_name (click_id int);
insert into test.test.table_name values (0),(1);
CREATE SECURE VIEW test.test.SECURE_VIEW AS
SELECT click_id as google_click_id
FROM test.test.table_name
WHERE click_id%2 = 1;
CREATE VIEW test.test.NORMALVIEW AS
SELECT click_id
FROM test.test.SECURE_VIEW AS a
LEFT JOIN test.test.table_name AS e
ON e.click_id = a.google_click_id;
Or some other all valid stuff, thus those views would not be created. for the select to fail on.
I wonder if you grab the DDL of the view and try recreate then (with different names) if they are still valid, or if the shape of some underlying table changed, or if something as be drop/recreate/renamed..
SELECT * from NORMALVIEW;
But yes, at the point open a support ticket.

BigQuery or SQL Server SPLIT query

I have searched around and can not find much on this topic. I have a table, that gets logging information. As a result the column I am interested in contains multiple values that I need to search against. The column is formatted in a php URL style. i.e.
/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32
This makes all searches end up with really long regexes to get data. Then join statements to combine data.
Is there a way in BigQuery, or SQL Server that I can pull the information from that column and put it into new columns?
Example:
The information I would like extracted begins after the ?, and ends at &, The string can sometimes be longer, and contains additional headers.
Thanks,
Below is for BigQuery Standard SQL and addresses below aspect of your question
Is there a way in BigQuery, ... that I can pull the information from that column and put it into new columns?
#standardSQL
CREATE TEMP FUNCTION parseColumn(kv STRING, column_name STRING) AS (
IF(SPLIT(kv, '=')[OFFSET(0)]= column_name, SPLIT(kv, '=')[OFFSET(1)], NULL)
);
WITH `project.dataset.table` AS (
SELECT '/test/test.aspx?extra=abc&DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url UNION ALL
SELECT '/test/test.aspx?DS_Vendor=55192&DS_ProdVer=4.30.100.0&more=123&DS_ProdLang=DE&DS_Product=MTE&DS_OfficeBits=64'
)
SELECT
MIN(parseColumn(kv, 'DS_Vendor')) AS DS_Vendor,
MIN(parseColumn(kv, 'DS_ProdVer')) AS DS_ProdVer,
MIN(parseColumn(kv, 'DS_ProdLang')) AS DS_ProdLang,
MIN(parseColumn(kv, 'DS_Product')) AS DS_Product,
MIN(parseColumn(kv, 'DS_OfficeBits')) AS DS_OfficeBits
FROM `project.dataset.table`,
UNNEST(REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')) AS kv
GROUP BY url
with the result as below
Row DS_Vendor DS_ProdVer DS_ProdLang DS_Product DS_OfficeBits
1 55039 7.90.100.0 EN MTT 32
2 55192 4.30.100.0 DE MTE 64
Below is also addressed
The string can sometimes be longer, and contains additional headers.
One example using BigQuery (with standard SQL):
SELECT REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')
FROM (
SELECT '/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url
)
This returns the parts of the URL as an ARRAY<STRING>. To go one step further, you can get back an ARRAY<STRUCT<key STRING, value STRING>> with a query of this form:
SELECT
ARRAY(
SELECT AS STRUCT
SPLIT(part, '=')[OFFSET(0)] AS key,
SPLIT(part, '=')[OFFSET(1)] AS value
FROM UNNEST(REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')) AS part
) AS keys_and_values
FROM (
SELECT '/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url
)
...or with the keys and values as top-level columns:
SELECT
SPLIT(part, '=')[OFFSET(0)] AS key,
SPLIT(part, '=')[OFFSET(1)] AS value
FROM (
SELECT '/test/test.aspx?DS_Vendor=55039&DS_ProdVer=7.90.100.0&DS_ProdLang=EN&DS_Product=MTT&DS_OfficeBits=32' AS url
)
CROSS JOIN UNNEST(REGEXP_EXTRACT_ALL(url, r'[?&]([^?&]+)')) AS part

SQL Duplicate column names error in Create View, even with aliases

The error is oddly specific, but I've just about honed in where it's occurring. The standard fix doesn't seem to be working though.
Here's where the error occurs. It's a big statement, so I'm just posting where I've found the error
CREATE OR REPLACE VIEW SalesInvoiceDoc
AS
( SELECT si.salinv_Num, si.salinv_Terms, si.salinv_SaleDate,
es.empName AS SalesAgent, man.empName AS ApprovingManager,
si.salinv_ApproveDate, ...
... FROM service_invoice si
JOIN employee es
ON (es.empID = si.salinv_EmpID)
JOIN employee man
ON (man.empID = si.salinv_ManID)
Essentially it's a Sales invoice document with a sales agent and approving manager. Both are stored in the employee table with a subtype discriminator set up for 'manager' or 'sales', and views for the subtype children tables to avoid duplication errors.
I've supplied aliases to try and avoid duplicate columns, but when I run this script, I get the duplicate column names error:
ORA-00957: duplicate column name
Does anyone know how to resolve this? Is it even possible? Any help would be greatly appreciated. Thank you in advance!
Edit: here's the full statement
CREATE OR REPLACE VIEW SalesInvoiceDoc
AS
( SELECT si.salinv_Num, si.salinv_Terms, si.salinv_SaleDate,
es.empName AS SalesAgent,
man.empName AS ApprovingManager, si.salinv_ApproveDate,
sc.custName, sc.custHouse, sc.custCity,
sc.custState, sc.custZIP, sc.custPhone, sc.custEmail,
sv.vehicle_VIN, sv.vehicle_year, sv.vehicle_make,
sv.vehicle_model, sv.vehicle_ext_color, sv.vehicle_trim,
sv.vehicle_list_base_price, sv.vehicle_mileage, sv.vehicle_condition,
sv.vehicle_description,
ti.vehicle_make, ti.vehicle_year, ti.vehicle_model, ti.vehicle_VIN,
ti.tradein_allowance,
sv.vehicle_list_base_price "SellingPrice", sv.shipping "Shipping",
ti.tradein_allowance "TradeAllowance",
(sv.vehicle_list_base_price + sv.shipping - ti.tradein_allowance) "Subtotal",
(sv.vehicle_list_base_price + sv.shipping - ti.tradein_allowance)*.0825 "Taxes",
(sv.vehicle_list_base_price + sv.shipping - ti.tradein_allowance)*1.0825 "TotalSellingPrice"
FROM sales_invoice si
JOIN employee es
ON (es.empID = si.salinv_EmpID)
JOIN employee man
ON (man.empID = si.salinv_ManID)
JOIN customer sc
ON (sc.custID = si.salinv_CustID)
JOIN vehicle sv
ON (sv.vehicle_VIN = si.salinv_SalVIN)
LEFT OUTER JOIN vehicle ti
ON (ti.vehicle_VIN = si.salinv_tiVIN)
);
You are duplicating column names from 2 different tables:
sv.vehicle_VIN,
sv.vehicle_year,
sv.vehicle_make,
sv.vehicle_model
and
ti.vehicle_make,
ti.vehicle_year,
ti.vehicle_model,
ti.vehicle_VIN
The resulting column name does not include the table alias.
Issue is cause sv.vehicle_VIN is appearing twice in your query and so does other columns. See below. You need to alias them all accordingly
**sv.vehicle_VIN**, **sv.vehicle_year**, **sv.vehicle_make**, **sv.vehicle_model**,
**ti.vehicle_make**, **ti.vehicle_year**, **ti.vehicle_model**, **ti.vehicle_VIN**,

SQL - How can I return a value from a different table base on a parameter?

SQL - How can I return a value from a different table base on a parameter
First time poster, long time reader:
I am using a custom Excel function that allows be to pass parameters and build a SQL string that returns a value. This is working fine. However, I would like to choose among various tables based on the parameters that are passed.
At the moment I have two working functions with SQL statements look like this:
_______FUNCTION ONE________
<SQLText>
SELECT PRODDTA.TABLE1.T1DESC as DESCRIPTION
FROM PRODDTA.TABLE1
WHERE PRODDTA.TABLE1.T1KEY = '&PARM02'</SQLText>
_______FUNCTION TWO________
<SQLText>
SELECT PRODDTA.TABLE2.T2DESC as DESCRIPTION
FROM PRODDTA.TABLE2
WHERE PRODDTA.TABLE2.T2KEY = '&PARM02'</SQLText>
So I am using IF logic in Excel to check the first parameter and decide which function to use.
It would be much better if I could do a single SQL statement that could pick the right table based on the 1st parameter. Logically something like this:
_______FUNCTIONS COMBINED________
IF '&PARM02' = “A” THEN
SELECT PRODDTA.TABLE1.T1DESC as DESCRIPTION
FROM PRODDTA.TABLE1
WHERE PRODDTA.TABLE1.T1KEY = '&PARM02'
ELSE IF '&PARM02' = “B” THEN
SELECT PRODDTA.TABLE2.T2DESC as DESCRIPTION
FROM PRODDTA.TABLE2
WHERE PRODDTA.TABLE2.T2KEY = '&PARM02'
ELSE
DESCRIPTION = “”
Based on another post Querying different table based on a parameter I tried this exact syntax with no success
<SQLText>
IF'&PARM02'= "A"
BEGIN
SELECT PRODDTA.F0101.ABALPH as DESCRIPTION
FROM PRODDTA.F0101
WHERE PRODDTA.F0101.ABAN8 = '&PARM02'
END ELSE
BEGIN
SELECT PRODDTA.F4801.WADL01 as DESCRIPTION
FROM PRODDTA.F4801
WHERE PRODDTA.F4801.WADOCO = '&PARM02'
END</SQLText>
You could try using a JOIN statement.
http://www.sqlfiddle.com/#!9/23461d/1
Here is a fiddle showing two tables.
The following code snip will give you the values from both tables, using the Key as the matching logic.
SELECT Table1.description, Table1.key, Table2.description
from Table1
Join Table2 on Table1.key = Table2.key
Here's one way to do it. If PARM03='Use Table1' then the top half of the union will return records and vice versa. This won't necessarily product good performance though. You should consider why you are storing data in this way. It looks like you are partitioning data across different tables which is a bad idea.
SELECT PRODDTA.TABLE1.T1DESC as DESCRIPTION
FROM PRODDTA.TABLE1
WHERE PRODDTA.TABLE1.T1KEY = '&PARM02'
AND &PARM03='Use Table1'
UNION ALL
SELECT PRODDTA.TABLE2.T2DESC as DESCRIPTION
FROM PRODDTA.TABLE2
WHERE PRODDTA.TABLE2.T2KEY = '&PARM02'</SQLText>
AND &PARM03='Use Table2'

Stored Procedure with two input params and multiple matches and create view with in

I am not much strong in SQL, so looking for some help.
First I am looking for suggestion for the best way to implement this logic in SQL and then some sample code to implement.
My portal is going to connect Students and Training Providers.
Students: Select what courses (multiple) they want, type of delivery (online, class room), Industry(domain) to which the course to be targeted more, Location Preference.
Training Providers: Select what courses offering (so one record for each course), offering locations, type of delivery for each course, industries (multiple) it is targeting.
When student login:
I would like to create SP which in turn create view to store the matched records of the Training Providers data which matches that student needs of that StudentID, CourseID passed to SP
I have created the following sp ( but not included create view part as I am not sure how to do this)
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
ALTER PROCEDURE [dbo].[sp_TPsMatched2StuCourse]
-- Add the parameters for the stored procedure here
#StuID int,
#CourseID int
AS
BEGIN
Select TP.MemID,TP.PastExp,SN.DeliveryType,SN.LocPref,SN.Industry,SC.CourseID from
tbl_TrainingProvider as TP , tbl_StuCourses as SC, tbl_StuNeeds SN
where SN.CourseID = #CourseID and SN.StuID = #StuID and
SN.DeliveryType in (TP.DeliveryMode) and
SN.LocPref IN (TP.LocOffering) and
SN.Industry IN (TP.Industries)
END
--- exec sp_ELsMatched2EntProp 1, 1
Why I need to put the data is as follows:
Assume the data is stored in that dynamic view and that would be bind to datagrid. Student then select interested TPs. Then only contact details would be shared to each other and this cannot be reveresed. So I would put this interested data in another table later. Every time data changes, hence the matches. Student can change some of his/her needs or new TPs join etc so view to be temparory.
when I executed this using above command, I am not getting data though it matches few records. What is wrong I am doing.
Any help would be greatly appreciated.
You are not getting expected results because you filter out too many records in WHERE( I'm talking about this part : SN.DeliveryType in (TP.DeliveryMode) and
SN.LocPref IN (TP.LocOffering) and SN.Industry IN (TP.Industries)). I'd recommend to use JOIN ... ON instead of specifying all tables in FROM and join condition in WHERE. I'm not sure what you want exactly, but I believe you are looking for
FROM tbl_StuNeeds SN
LEFT JOIN tbl_TrainingProvider as TP ON (TP.DeliveryMode = SN.DeliveryType AND
SN.LocPref = TP.LocOffering AND TP.Industries = SN.Industry)
WHERE SN.CourseID = #CourseID and SN.StuID = #StuID
Also, there is no join conditions in your code for tbl_StuCourses as SC which results in cross-join.
Finally, why do you need a stored procedure at all? From what I see in your example, a table-valued function will work better:
CREATE FUNCTION [dbo].getTPsMatched2StuCourse(#StuID INT,#CourseID INT)
RETURNS TABLE AS
RETURN
Select .... ;

Resources