I need to rename the column base on the value I give in it.
SELECT TOP 1
[Pratice_Id] = [OID]// id
, [Province] = '' //province
, [Country] = 'US'// country
FROM [tbl_Office]
if the country equals to US I want to change columnName [Province] to State
I would strongly suggest a column STATE_PROVINCE, however, if you MUST and you are not opposed to a temp table, perhaps something like this
Example
Select Top 1 *
Into #Temp
From YourTable
Where ...
Order By ...
If ( Select Top 1 Country From #Temp ) = 'US'
Select [Pratice_Id]
,[State] = [Province]
,[Country]
From #Temp
Else
Select * from #Temp
Returns
Pratice_Id State Country
1 RI US
Personally, I would provide both
Declare #YourTable table ([Pratice_Id] int,[Province] varchar(50),[Country] varchar(50))
Insert Into #YourTable values
(1,'RI','US')
,(2,'Alberta','Canada')
Select [Pratice_Id]
,[State] = case when [Country]='US' then Province else '' end
,[Province] = case when [Country]<>'US' then Province else '' end
,[Country]
From #YourTable
Returns
Pratice_Id State Province Country
1 RI US
2 Alberta Canada
Related
I have a column called empl_type_multi which is just a comma delimited column, each value is a link to another table called custom captions.
For instance, i might have the following as a value in empl_type_multi:
123, RHN, 458
Then in the custom_captions table these would be individual values:
123 = Dog
RHN = Cat
458 = Rabbit
All of these fields are NTEXT.
What i am trying to do is convert the empl_type_multi column and chance it to the respective names in the custom_captions table, so in the example above:
123, RHN, 458
Would become
Dog, Cat, Rabbit
Any help on this would be much appreciated.
----- EDIT ------------------------------------------------------------------
Ok so ive managed to convert the values to the corresponding caption and put it all into a temporary table, the following is the output from a CTE query on the table:
ID1 ID2 fName lName Caption_name Row_Number
10007 22841 fname1 lname1 DENTAL ASSISTANT 1
10007 22841 fname1 lname1 2
10007 22841 fname1 lname1 3
10008 23079 fname2 lname2 OPS WARD 1
10008 23079 fname2 lname2 DENTAL 2
10008 23079 fname2 lname2 3
How can i update this so that anything under caption name is added to the caption name of Row_Number 1 separated by a comma?
If i can do that all i need to do is delete all records where Row_Number != 1.
------ EDIT --------------------------------------------------
The solution to the first edit was:
WITH CTE AS
(
SELECT
p.ID1
, p.ID2
, p.fname
, p.lname
, p.caption_name--
, ROW_NUMBER() OVER (PARTITION BY p.id1ORDER BY caption_name DESC) AS RN
FROM tmp_cs p
)
UPDATE tblPerson SET empType = empType + ', ' + c.Data
FROM CTE c WHERE [DB1].dbo.tblPerson.personID = c.personID AND RN = 2
And then i just incremented RN = 2 until i got 0 rows affected.
This was after i ran:
DELETE FROM CTE WHERE RN != 1 AND Caption_name = ''
select ID1, ID2, fname, lname, left(captions, len(captions) - 1) as captions
from (
select distinct ID1, ID2, cast(fname as nvarchar) as fname, cast(lname as nvarchar) as lname, (
select cast(t1.caption_name as nvarchar) + ','
from #temp as t1
where t1.ID1 = t2.ID1
and t1.ID2 = t2.ID2
and cast(caption_name as nvarchar) != ''
order by t1.[row_number]
for xml path ('')) captions
from #temp as t2
) yay_concatenated_rows
This will give you what you want. You'll see casting from ntext to varchar. This is necessary for comparison because many logical ops can't be performed on ntext. It can be implicitly cast back the other way so no worries there. Note that when casting I did not specify length; this will default to 30, so adjust as varchar(length) as needed to avoid truncation. I also assumed that both ID1 and ID2 form a composite key (it appears this is so). Adjust the join as you need for the relationship.
you have just shared your part of problem,not exact problem.
try this,
DECLARE #T TABLE(ID1 VARCHAR(50),ID2 VARCHAR(50),fName VARCHAR(50),LName VARCHAR(50),Caption_name VARCHAR(50),Row_Number INT)
INSERT INTO #T VALUES
(10007,22841,'fname1','lname1','DENTAL ASSISTANT', 1)
,(10007,22841,'fname1','lname1', NULL, 2)
,(10007,22841,'fname1','lname1', NULL, 3)
,(10008,23079,'fname2','lname2','OPS WARD', 1)
,(10008,23079,'fname2','lname2','DENTAL', 2)
,(10008,23079,'fname2','lname2', NULL, 3)
SELECT *
,STUFF((SELECT ','+Caption_name
FROM #T T1 WHERE T.ID1=T1.ID1 FOR XML PATH('')
),1,1,'')
FROM #T T
You can construct the caption_name string easily by looping through while loop
declare #i int = 2,#Caption_name varchar(100)= (select series from
#temp where Row_Number= 1)
while #i <= (select count(*) from #temp)
begin
select #Caption_name = #Caption_name + Caption_name from #temp where Row_Number = #i)
set #i = #i+1
end
update #temp set Caption_name = #Caption_name where Row_Number = 1
and use case statement to remove null values
(select case when isnull(Caption_name ,'') = '' then
'' else ',' + Caption_name end
I'm trying to group a SELECT like you'd normally do - AND at the same time make a new "shared/aggregate group" adding that to the original result-set without a secondary SELECT and UNION.
The secondary SELECT and UNION is out of the question since the real use of this is with some very big tables, with a lot of joins, so it would be waay to slow. So the UNION way is definitely out of the question.
I've tried my best to illustrate this with the following simplified example:
BEGIN TRAN
CREATE TABLE #MyTable
(
id INT,
name VARCHAR(255)
)
INSERT INTO #MyTable VALUES (1,'cola');
INSERT INTO #MyTable VALUES (2,'cola');
INSERT INTO #MyTable VALUES (3,'cola');
INSERT INTO #MyTable VALUES (4,'fanta');
INSERT INTO #MyTable VALUES (5,'fanta');
INSERT INTO #MyTable VALUES (6,'fanta');
INSERT INTO #MyTable VALUES (7,'water');
INSERT INTO #MyTable VALUES (8,'water');
INSERT INTO #MyTable VALUES (9,'water');
INSERT INTO #MyTable VALUES (10,'cola');
INSERT INTO #MyTable VALUES (11,'cola');
SELECT
CASE
WHEN name = 'cola' OR name = 'fanta'
THEN 'soda'
ELSE
name
END as name,
COUNT(distinct id) as count
FROM #MyTable
GROUP BY name
ROLLBACK TRAN
Actual output:
soda 5
soda 3
water 3
Desired output:
cola 5
fanta 3
soda 8 <- this is the "shared/aggregate group"
water 3
As Panagiotis Kanavos correctly pointed out in the comment above, this can be done using ROLLUP:
BEGIN TRAN
CREATE TABLE #BeverageType
(
name VARCHAR(255)
)
INSERT INTO #BeverageType VALUES ('Soda');
INSERT INTO #BeverageType VALUES ('Other');
CREATE TABLE #UserBeverage
(
id INT,
name VARCHAR(255)
)
INSERT INTO #UserBeverage VALUES (1,'cola');
INSERT INTO #UserBeverage VALUES (2,'cola');
INSERT INTO #UserBeverage VALUES (3,'cola');
INSERT INTO #UserBeverage VALUES (1,'fanta'); -- <- NOTE: user 1 drinks both cola and fanta so the as intended the user is only counted 1 time in the ROLLUP 'Soda' group (7)
INSERT INTO #UserBeverage VALUES (5,'fanta');
INSERT INTO #UserBeverage VALUES (6,'fanta');
INSERT INTO #UserBeverage VALUES (7,'water');
INSERT INTO #UserBeverage VALUES (8,'water');
INSERT INTO #UserBeverage VALUES (9,'water');
INSERT INTO #UserBeverage VALUES (10,'cola');
INSERT INTO #UserBeverage VALUES (11,'cola');
SELECT ub.name, bt.name AS groupName, COUNT(distinct id) as uniqueUserCount
FROM #UserBeverage as ub
JOIN #BeverageType as bt
ON CASE
WHEN (ub.name = 'water')
THEN 'Other'
ELSE
'Soda'
END = bt.name
GROUP BY ROLLUP(bt.name, ub.name)
ROLLBACK TRAN
Outputs:
cola Soda 5
fanta Soda 3
water Other 3
NULL Other 3
NULL Soda 7
NULL NULL 10
You should repeat CASE statement everywhere.
SELECT
CASE WHEN name = 'cola' OR name = 'fanta'
THEN 'soda' ELSE name END as name,
COUNT((CASE WHEN name = 'cola' OR name = 'fanta'
THEN 'soda' ELSE name END)) as count
FROM #MyTable
GROUP BY CASE WHEN name = 'cola' OR name = 'fanta'
THEN 'soda' ELSE name END
+-------+-------+
| name | count |
+-------+-------+
| soda | 8 |
+-------+-------+
| water | 3 |
+-------+-------+
Can I suggest to use a subquery:
SELECT name, count(*) AS count
FROM (SELECT CASE WHEN name = 'cola' OR name = 'fanta'
THEN 'soda' ELSE name END as name
FROM #MyTable) x
GROUP BY name;
If you need the aggregate as well as the individual products, then an alternative may be to use a UNION and select the aggregates as a second query.
SELECT name, count(distinct id) as count
FROM #MyTable
GROUP BY name
UNION
SELECT 'SODA', COUNT(distinct id) as count
FROM #MyTable
WHERE name = 'cola' or name ='fanta'
You might also use Søren Høyer Kristensen's summary table to get the aggregate names if you need more groupings.
I have a table with duplicate rows, however, some of the duplicate rows have columns does not contain data for the same column. How can I remove/ignore only those row where columns are blank? In some instances:
Name Employee# Location City
-----------------------------------------
BowerT 48999 NJ Foods
BowerT 48999 NJ Foods Pearl
BowerT 48999 NJ Foods Johns
BowerT 48999 NJ Foods Johns
I'm using with CTE to delete duplicate, however, if 2nd, 3rd, or 4th row has the data I need for that column, I lose it because these are greater than row 1.
;With hrEmployee as
(
Select
*,
Row_Number () Over (Partition BY Employee_Number order by Employee_Number) As RowNumber
From
[dbo].[hrEmployee]
Where
Employee_Number = '48999'
)
Delete hrEmployees
where RowNumber > 1
What am I missing?
Here is an entire example the relevant code change is:
ROW_NUMBER() OVER (PARTITION BY Employee_Number ORDER BY
CASE WHEN ISNULL(City,'') = '' THEN 1 ELSE 0 END
) as RowNumber
What that does is simply ORDER your results of what you want to keep by saying if the City is null or '' (blank) make it last. You can rank your results anyway you want by specifying different order in your ORDER BY.
DECLARE #Table AS TABLE (Name VARCHAR(10), Employee_Number INT, Location VARCHAR(20), City VARCHAR(20))
INSERT INTO #Table VALUES ('BowerT',48999,'NJ Foods',NULL)
,('BowerT',48999,'NJ Foods','Pearl')
,('BowerT',48999,'NJ Foods','Johns')
,('BowerT',48999,'NJ Foods','Johns')
SELECT *
FROM
#Table
;WITH hrEmployee AS (
SELECT
*
,ROW_NUMBER() OVER (PARTITION BY Employee_Number ORDER BY
CASE WHEN ISNULL(City,'') = '' THEN 1 ELSE 0 END
) as RowNumber
FROM
#Table
where Employee_Number = '48999'
)
DELETE
FROM
hrEmployee
WHERE
RowNumber > 1
SELECT *
FROM
#Table
Sorry for the confusing title, but I couldn't find a better way to explain it.
I have some results where one row should populate an entire row if a specific code is found.
Here's the data:
PartID CustomerID Status Qty Notes
1000 900123 1 10 NULL
911 900123 1 5 NULL
Here's what I want it to do:
PartID CustomerID Status Qty Notes
1000 900123 1 10 911
911 900123 1 5 911
How could I write a query to give the notes field a value of 911 if one PartID has a value of 911?
EDIT: Thanks for the replies everyone, but I was hoping I could use a Select statement to accomplish this. I accomplished this by using a temp table, updating if the customer has a 911 in their order, updated only that customer's notes with 911, then queried the temp table for the data.
Try this:
UPDATE Table
SET Notes=(CASE WHEN (SELECT Count(1) FROM Table Where PartId=911)>0 THEN 911 ELSE NULL END)
or
UPDATE t
SET t.Notes= t2.PartId
FROM Table t
LEFT JOIN Table t2 on t2.PartId=911
update #t
set Notes=(select PartID from #t where PartID in(911))
select * from #t
SEE DEMO
You could use something like
update MyTable
set Notes = '911'
where (select count(1) from #MyTableVar where PartID = 911) > 0
For example:
DECLARE #MyTableVar table( PartID int,
CustomerID int,
Status int,
Qty int,
Notes varchar(50));
insert into #MyTableVar(PartID, CustomerID, Status, Qty, Notes)
values (1000, 900123, 1, 10, null)
insert into #MyTableVar(PartID, CustomerID, Status, Qty, Notes)
values (911, 900123, 1, 5, null)
select * from #MyTableVar
update #MyTableVar
set Notes = '911'
where (select count(1) from #MyTableVar where PartID = 911) > 0
select * from #MyTableVar
EDIT:
To just change the returned values, rather than updating the database you could do the following (based on the above example):
select
mtv.PartID,
mtv.CustomerID,
mtv.Status,
mtv.Qty,
case when (select count(1) from #MyTableVar where PartID = 911) > 0
then '911'
else mtv.Notes
end as Notes
from
#MyTableVar mtv
select PartID, CustomerID, Status, Qty,
case when exists(select * from notes where PartID = 911) then '911' else Notes end Notes
from notes
I would recommend you to split the logic in two separate moves:
--1. check condition
declare #IsPartIDDetected int = 0;
if exists (select PartID from Notes where PartID = 911 )
set #IsPartIDDetected = 1;
--2. get filteredoutput
select PartID, CustomerID, Status, Qty,
case when #IsPartIDDetected = 1 then '911' else COALESCE(Notes,'') end as Notes
from Orders
This solution has an optimal execution plan and will cost less RAM.
COALESCE command added as an example of NULL values processed.
You can also wrap it into single CTE statement:
WITH partCondition as (
select top 1 PartID as conditon from Notes where PartID = 911
)
select PartID, CustomerID, Status, Qty,
case
when exists ( select * from partCondition )
then 911 --conditon met
else Notes end --condition NOT met
as Notes
from Orders;
This will help to lower execution costs.
Not clear what one partID means
Do you mean CustomerID with one partID of 911?
run these two statements:
update customer
set notes = 911
where partID = 911
and notes <> 911;
update c2
set c2.notes = 911
from customer c1
join customer c2
on c2.CustomerID = c1.CustomerID
and c1.partID = 911
and c2.partID <> 911
and (c2.notes <> 911 or c2.notes is null);
this one statement might do it but not sure it would be faster:
update c2
set c2.notes = 911
from customer c1
join customer c2
on c2.CustomerID = c1.CustomerID
and c1.partID = 911
and (c2.notes <> 911 or c2.notes is null);
This question already has answers here:
Oracle: how to INSERT if a row doesn't exist
(9 answers)
Closed 9 years ago.
I have a simple question - for examples sake let's have the table
CITY(ID,Name).
An idea would be that when I want to add new city I first make sure it's not already in the table CITY.
Code example would be:
IF cityName NOT IN (SELECT name FROM city) THEN
INSERT INTO City(ID, NAME) VALUES(100, cityName);
ELSE
Raise namingError;
END IF;
However I can't have that subquery inside if statement so what should I replace it with? Any kind of list or variable or trick that I could use?
IF NOT EXISTS(SELECT 1 FROM CITY WHERE NAME = <CITYNAME>)
INSERT INTO City(ID, NAME) VALUES(100, cityName);
OR
INSERT INTO City
SELECT 100,'cityName'
FROM dual
WHERE NOT EXISTS (SELECT 1
FROM CITY
WHERE name = cityname
)
I read the second query here
I don't have a database to try this out, but this should work
You could use a merge command to perform the insert into the table. While the merge command is used to perform an insert if the data is not present or an update if the data is present in this case since you just have two fields it will just preform the insert for you.
This is useful if you want to take data from one or more tables and combine them into one.
MERGE INTO city c
USING (SELECT * FROM city_import ) h
ON (c.id = h.id and c.city = h.city)
WHEN MATCHED THEN
WHEN NOT MATCHED THEN
INSERT (id, city)
VALUES (h.id, h.city);
http://www.oracle-base.com/articles/9i/merge-statement.php
If it was me I'd probably do something like
DECLARE
rowCity CITY%ROWTYPE;
BEGIN
SELECT * INTO rowCity FROM CITY c WHERE c.NAME = cityName;
-- If we get here it means the city already exists; thus, we raise an exception
RAISE namingError;
EXCEPTION
WHEN NO_DATA_FOUND THEN
-- cityName not found in CITY; therefore we insert the necessary row
INSERT INTO City(ID, NAME) VALUES(100, cityName);
END;
Share and enjoy.
Two options:
One using INSERT INTO ... SELECT with a LEFT OUTER JOIN; and
The other using MERGE
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE city (
ID NUMBER(2) PRIMARY KEY,
NAME VARCHAR2(20)
);
INSERT INTO city
SELECT 1, 'City Name' FROM DUAL;
CREATE TABLE city_errors (
ID NUMBER(2),
NAME VARCHAR2(20),
TS TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
ERROR VARCHAR2(20)
);
Query 1:
DECLARE
city_id CITY.ID%TYPE := 2;
city_name CITY.NAME%TYPE := 'City Name';
namingError EXCEPTION;
PRAGMA EXCEPTION_INIT( namingError, -20001 );
BEGIN
INSERT INTO city ( id, name )
SELECT city_id,
city_name
FROM DUAL d
LEFT OUTER JOIN
city c
ON ( c.name = city_name )
WHERE c.id IS NULL;
IF SQL%ROWCOUNT = 0 THEN
RAISE namingError;
END IF;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- Do something when duplicate ID found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate ID' );
WHEN namingError THEN
-- Do something when duplicate Name found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate Name' );
END;
Results:
Query 2:
DECLARE
city_id CITY.ID%TYPE := 3;
city_name CITY.NAME%TYPE := 'City Name';
namingError EXCEPTION;
PRAGMA EXCEPTION_INIT( namingError, -20001 );
BEGIN
MERGE INTO city c
USING ( SELECT city_id AS id,
city_name AS name
FROM DUAL ) d
ON ( c.Name = d.Name )
WHEN NOT MATCHED THEN
INSERT VALUES ( d.id, d.name );
IF SQL%ROWCOUNT = 0 THEN
RAISE namingError;
END IF;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
-- Do something when duplicate ID found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate ID' );
WHEN namingError THEN
-- Do something when duplicate Name found.
INSERT INTO city_errors ( ID, NAME, ERROR ) VALUES ( city_id, city_name, 'Duplicate Name' );
END;
Results:
Query 3:
SELECT * FROM City
Results:
| ID | NAME |
|----|-----------|
| 1 | City Name |
Query 4:
SELECT * FROM City_Errors
Results:
| ID | NAME | TS | ERROR |
|----|-----------|--------------------------------|----------------|
| 2 | City Name | January, 02 2014 20:01:49+0000 | Duplicate Name |
| 3 | City Name | January, 02 2014 20:01:49+0000 | Duplicate Name |