I'm running select statements in a loop with a cursor to collect data from different tables;
Quick (NOT WORKING) example;
select DISTINCT(ordernr) from orders
INSERT INTO newtable (select Crs.ordernr as ordernr, value1 as value from table2 where table2.ordernr = Crs.ordernr );
INSERT INTO newtable (select Crs.ordernr as ordernr, value2 as value from table3 where tabel3.ordernr=Crs.ordernr ;
)
LOOP
END LOOP;
END;
What I could like is just one insert statement which insert just the biggest value of boths select statements.
I've tried to work with greatest function in my loop but i'm running stuck. Both datatypes are the same for value1 and value2
insert into newtable(select crs.ordernr as ordernr, greatest
(
select value1 as value from table1 where condition=1, select value2 as value from table2 where condition=1)
)
);
Is it possible with a select case or other way to return only one value based on conditions? For example the biggest value of value1 or value2?
You can use the greatest function and provide subqueries to it, but - follow the syntax, i.e. enclose each of them (select statements) into its own parenthesis.
Something like this:
SQL> select greatest ( (select max(sal) from emp where job = 'CLERK'),
2 (select max(sal) from emp where job = 'ANALYST')
3 ) greatest_salary
4 from dual;
GREATEST_SALARY
---------------
3450
SQL>
I have no idea what is this:
insert into newtable(select crs.ordernr as ordernr
-----------------------------
supposed to do; what is crs? Where's the from clause?
From Oracle 12, you can use:
INSERT INTO newtable (ordernr, value)
SELECT *
FROM (
SELECT Crs.ordernr as ordernr,
value1 as value
FROM table2
WHERE table2.ordernr = Crs.ordernr
UNION ALL
SELECT Crs.ordernr,
value2
FROM table3
WHERE table3.ordernr=Crs.ordernr
)
ORDER BY value DESC
FETCH FIRST ROW ONLY;
This will mean that if you extend the query to extract more columns and you want the highest of one column and the corresponding values of the other columns then the values will all come from that one row with the highest value.
db<>fiddle here
I have a table form which I need to extract some information. This table has an oracle spatial (MDSYS.SDO_GEOMETRY) column, from which I also need some data.
I started out with a simple query like this:
select id, field1, field2
FROM my_table;
After that, I was able to loop over the result to extract the data that was in the spatial column:
SELECT *
FROM TABLE (SELECT a.POSITIONMAP.sdo_ordinates
FROM my_table
WHERE ID = 18742084);
The POSITIONMAP.sdo_ordinates seems to usually hold 4 values, like these:
100050,887
407294,948
0,577464740471056
-0,816415625470689
I need the last 2 values. I can achieve that by changing the query into this:
SELECT * FROM
(SELECT rownum AS num,
column_value AS orientatie
FROM TABLE (SELECT a.POSITIONMAP.sdo_ordinates
FROM my_table
WHERE ID = 18742084))
WHERE num IN (3,4)
Looping over every row from my first query to extract the data from the POSITIONMAP column is of course not very performance friendly, so my query becomes slow very quickly.
I would like to retrieve all information in one query, but there are a few things that prevent me from doing so.
Not every row in the table has data in POSITIONMAP
Some rows do have data in POSITIONMAP, but they only contain 2 values (so not the 3rd and 4th value that I am looking for.
I need the data in one row for every row in the table (using the previous query would result in duplicate rows
The closest I got is:
select
id,
field1,
field2
t.*
FROM my_table v,
table (v.POSITIONMAP.sdo_ordinates) t
This gives my 4 rows for every row in my_table.
As soon as I try to put the rownum condition into this query, I get an error: "invalid user.table.column, table.column, or column specification"
Is there any way to combine what I want to do into 1 query?
You can use sdo_util.getvertices as follows:
select t.x,t.y
from my_table mt
,table(sdo_util.getvertices(mt.positionmap)) t
where t.id = 2
I'm assuming that your geometries are lines (gtype=2002) and points (gtype= 2001). If you want X,Y values for lines and empty values for point you can filter on the sdo_gtype property of the geometry object.
select t.x,t.y
from my_table mt
,table(sdo_util.getvertices(mt.positionmap)) t
where t.id = 2
and mt.positionmap.sdo_gtype=2002
union all
select null as X,
null as Y
from my_table mt
where mt.positionmap.sdo_gtype=2001
One method is to use the ROW_NUMBER() analytic function:
SELECT *
FROM (
select id,
field1,
field2,
t.*,
ROW_NUMBER() OVER ( PARTITION BY v.id ORDER BY ROWNUM ) AS rn
FROM my_table v,
TABLE( v.POSITIONMAP.sdo_ordinates ) t
)
WHERE rn IN ( 3, 4 )
You see that the SKU1 has 2 rows, but actually the content of these 2 rows are the same, just the sequence of "b" and "c" makes difference.
What if I want to remove the duplicate rows as shown in the 2nd picture?
In Oracle there is a LEAST/GREATEST function that can realize it, but I used SQL Server, therefore it doesn't work following the instruction of the below post:
How to remove duplicate rows in SQL
If it's only 2 columns where the order should not matter for the group by?
Then you could use IIF (or a CASE WHEN) to calculate the maximum and minimum values.
And use those calculated values in the GROUP BY.
For example:
select Name,
MAX(Val1) as Val1,
MIN(Val2) as Val2
from Table1
GROUP BY Name,
IIF(Val2 is null or Val1 < Val2, Val1, Val2),
IIF(Val1 is null or Val1 < Val2, Val2, Val1);
For the example records that would give the result:
Name Val1 Val2
SKU1 20 10
SKU2 20 10
Or if you want to use a fancy XML trick :
select Name, max(Val1) as Val1, min(Val2) as Val2
from (
select *,
cast(
convert(XML,
concat('<n>',Val1,'</n><n>',Val2,'</n>')
).query('for $n in /n order by $n return string($n)'
) as varchar(6)) as SortedValues
from Table1
) q
group by Name, SortedValues;
The last method could be more usefull when there are more columns involved.
To actually remove the duplicates?
Here's an example that uses a table variable to demonstrate:
declare #Table1 TABLE (Id int, Name varchar(20), Val1 int, Val2 int);
Insert Into #Table1 values
(1,'SKU1',10,20),
(2,'SKU1',20,10),
(3,'SKU1',12,15),
(4,'SKU2',10,null),
(5,'SKU2',null,10),
(6,'SKU2',10,20);
delete from #Table1
where Id in (
select Id
from (
select Id,
row_number() over (partition by Name,
IIF(Val2 is null or Val1 < Val2, Val1, Val2),
IIF(Val1 is null or Val1 < Val2, Val2, Val1)
order by Val1 desc, Val2 desc
) as rn
from #Table1
) q
where rn > 1
);
select * from #Table1;
Please Use Max() and Min Function instead of least and greatest of oracle if used the follwoing steps and got the same result.
Create Table Transactions (Name varchar(255),Quantity1 int,Quantity2 int)
Insert Into Transactions values
('SKU1',10,20),
('SKU1',20,10),
('SKU2',10,20),
('SKU2',10,20)
Now I used the query below to find the solution of your answer
Select T1.Name,MAX(T1.Quantity1),MIN(T2.Quantity2) From Transactions T1
join Transactions T2
on T1.Name=T2.Name
group by T1.Name
Please Reply
greatest() can be simulated using a CASE expression
greatest(b,c) is the same as:
case
when b > c then b
else c
end
You can use this together with a distinct to remove your duplicates:
select distinct
a,
case when b > c then b else c end as x
from the_table
order by a;
Try %%physloc%%. It is the equivalent of oracle's RowId.
Find it
select *, %%physloc%% from [MyTable] where ...
Delete what you want
delete from [MyTable] where %%physloc%% = 0xDEADBEEF -- (your address)
Consider adding a Unique / Primary Key to prevent future occurrences.
SELECT * FROM abc where A='SKU1'and B=20 || A='SKU2'and B=10
a b c
SKU1 20 10
SKU2 10 20
This may seem a little complicated at first, but we can also use PIVOT/UNPIVOT to obtain the results
Below is the query
select *
from
(
select
*,
'quantity'+ cast(row_number() over (partition by name order by data) as nvarchar) cols
from
(
select
distinct name, data
from
(select * from transactions)s
unpivot
(
data for cols in (quantity1,quantity2)
)u
)s
)s
pivot
(
max(data) for cols in (quantity1,quantity2)
)p
From your question it is not clear whether you want to filter duplicates by row or duplicates by column. Let me describe both to make sure your question is addressed completely.
In Example 1, you can see that we have duplicate rows:
To filter them, just add the keyword DISTINCT to your query, as follows:
SELECT DISTINCT * FROM myTable;
It filters the duplicate rows and returns:
Hence, you don't need a least or greatest function in this case.
In Example 2, you can see that we have duplicates in the columns:
Here, SELECT DISTINCT * from abc will still return all 4 rows.
If we regard only the first column in the filtering, it can be achieved by the following query:
select distinct t.Col1,
(select top 1 Col2 from myTable ts where t.Col1=ts.Col1) Col2,
(select top 1 Col3 from myTable ts where t.Col1=ts.Col1) Col3
from myTable t
It will pick the first matching value in each column, so the result of the query will be:
The difference between Example 1 and this example is that it eliminated just the duplicate occurances of the values in Col1 of myTable and then returned the related values of the other columns - hence the results in Col1 and Col2 are different.
Note:
In this case you can't just join the table myTable because then you would be forced to list the columns in the select distinct which would return more rows then you want to have. Unfortunately, T-SQL does not offer something like SELECT DISTINCT ON(fieldname) i.e. you can't directly specify a distinct (single) fieldname.
You might have thought "why not use GROUP BY?" The answer of that question is here: With GROUP BY you are forced to either specify all columns which is a technical DISTINCT equivalent, or you need to use aggregate functions like MIN or MAX which aren't returning what you want either.
A more advanced query (you might have seen is once before!) which has the same result is:
SELECT Col1, Col2, Col3
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col1) AS RowNumber
FROM myTable
) t
WHERE RowNumber=1
This statement numbers each occurance of a value on Col1 in the subquery and then takes the first of each duplicate rows - which effectively is a grouping by Col1 (but without the disadvantages of GROUP BY).
N.B. In the examples above, I am assuming a table definition like:
CREATE TABLE [dbo].[myTable](
[Col1] [nvarchar](max) NULL,
[Col2] [int] NULL,
[Col3] [int] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
For the examples above, we don't need to declare a primary key column. But generally spoken you'll need a primary key in database tables, to be able to reference rows efficiently.
If you want to permanently delete rows not needed, you should introduce a primary key, because then you can delete the rows not displayed easily as follows (i.e. it is the inverse filter of the advanced query mentioned above):
DELETE FROM [dbo].[myTable]
WHERE myPK NOT IN
(SELECT myPK
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Col1 ORDER BY Col1) AS RowNumber
FROM [dbo].[myTable]
) t
WHERE RowNumber=1 and myPK=t.myPK)
This assumes you have added an integer primary key myPK which auto-increments (you can do that via the SQL Management Studio easily by using the designer).
Or you can execute the following query to add it to the existing table:
BEGIN TRANSACTION
GO
ALTER TABLE dbo.myTable ADD
myPK int NOT NULL IDENTITY (1, 1)
GO
ALTER TABLE dbo.myTable ADD CONSTRAINT
PK_myTable PRIMARY KEY CLUSTERED (myPK)
WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
ON [PRIMARY]
GO
ALTER TABLE dbo.myTable SET (LOCK_ESCALATION = TABLE)
GO
COMMIT
You can find some more examples here at MSDN.
COUNT(DATECREATED)
88708
26625
17092
how to create a select query for viewing this three values in single column as different column names like
COUNT(DATECREATED) COUNT(DATECREATED) COUNT(DATECREATED)
88708 26625 17092
88708
88708
If you just want 1 row with 3 rows as columns, then use this. Here col is the alias for your count statement.
with tbl as
(select rownum as rno,col from
(your existing query) t
)
select (select col from tbl where rno=1) col1 ,
(select col from tbl where rno=2) col2,
(select col from tbl where rno=3 ) col3
from dual
If there are more rows and you want to use them as column, then read about Dynamic pivot in Oracle and you shall get your answer.
Finally i did like this.. Thanks all for quick reply
select sum(colname) as aliasname, sum(colname) as aliasname, sum(colname) as aliasname from
(select count(colname) as colname,0 as colname,0 as colname from cof
union all
select 0,count(colname),0 from cof where colname is not null
union all
select 0,0,count(colname) from cof where colname is not null);
I am using SQL Server 2012 for my database. Now, I have one table with following details.
ID COLUMN1 COLUMN2
1 A B
Now i want result like this.
ID Values
1 A
1 B
Can any one suggest me how to do?
I know i can do using pivot or unpivot. but i dont know how to do? and is there other way to do this?
Please help me out to write query for the same.
Thanks in advance.
You can use UNPIVOT to get the final result:
select id, value
from yourtable
unpivot
(
value
for col in (COLUMN1, COLUMN2)
) u;
See SQL Fiddle with Demo
Or you can use CROSS APPLY to get it:
select id, value
from yourtable
cross apply
(
values ('COLUMN1', COLUMN1), ('COLUMN2', COLUMN2)
) c (col, value)
See SQL Fiddle with Demo
select id, col1 as value
from your_table
union all
select id, col2 as value
from your_table