In snowflake how do you do Minus all? I do not see an option in the documentation
There's no way to do it directly, but you can try to order your similar records, so the minus only affects one of them, sth like:
SELECT job, ROW_NUMBER()OVER(PARTITION BY job ORDER BY 1) rn
FROM emp
WHERE deptno=20
MINUS
SELECT job, ROW_NUMBER()OVER(PARTITION BY job ORDER BY 1) rn
FROM emp
WHERE deptno=30;
Not sure if this is what you are looking for, since your question is a bit vague, but this is the documentation link to the Snowflake MINUS operation:
https://docs.snowflake.com/en/sql-reference/operators-query.html#minus-except
Related
This question is a little broad, so apologies in advance.
The company I work for recently switched to a new system which uses SQL Server instead of Mysql and our team is tasked with bringing several old reports over. Because the new system models things a bit differently, we aren't aiming for 1-1 parity with old reports.
These are our current limitations:
We can only provide SSRS reports - only what can fit in a .rdl file
We can query the database and add views
We are unable to add stored procedures and functions due to some licensing agreement
We are also unable to add additional databases to the server
However, to my knowledge some of the reports will require:
Building tables by looping over data an arbitrary number of times (e.g. walking a bill of material structure)
some minor state tracking during evaluation, like running totals
I've tried to be clever and tackle the second requirement with a combination of CTEs and ROW_NUMBER, for example:
with t as
(
select
row_num = row_number() over (order by a),
a, b, c
from
table1
)
select
a,
(select sum(b) from t t2 where t2.row_num < t.row_num) as running_b,
(select sum(c) from t t3 where t3.row_num < t.row_num) as running_c
from
t
order by
row_num;
In this case row_number is required because a values could be identical.
However, SQL Server doesn't appear to do the math correctly for every row, or I have misunderstood something about the query. A co-worker has frequently complained about similar issues with the pivot function.
My question isn't about a single query though. We need to add more power to our queries within our current limitations, and I need some advice on how to do that.
Can anyone help?
UPDATE
In reference to the example query, I found that SQL Server gave me the expected results if I swap the subselect with a left self-join along with a group clause:
with t as
(
select
row_num = row_number() over (order by a),
a, b, c
from
table1
)
select
a,
sum(t2.b) as running_b,
sum(t2.c) as running_c
from
t
left join t t2 on t2.row_num < t.row_num
group by
t.row_num, t.a
order by
row_num;
Additionally, JacobH made me aware of Recursive CTEs, and I think that will help with the other issue. I think these two techniques solve my most pressing concerns.
Is the result of a SELECT like the one below using XQuery in SQL Server guaranteed to be in document order, that is in the original order the nodes are listed in the xml string?
DECLARE #x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>'
SELECT t.i.value('.', 'int')
FROM #x.nodes('/hey/#i') t(i)
I ask because in general SELECT statements do not guarantee an order unless one is provided.
Also, if this order is (or is not) guaranteed, is that documented somewhere officially, maybe on Microsoft's web site?
Last, is it possible to sort opposite of document order or do other strange sorts and queries based on the original document order from within the SELECT statement?
The
DECLARE #x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>'
is an example of an XML "sequence". By definition, without a sort order, the select should always come back in the documents original order.
As already mentioned, you can change the sort order. Here is one example:
SELECT t.i.value('.', 'int') as x, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as rn
FROM #x.nodes('/hey/#i') t(i)
order by rn desc
Here is some information about sequences on the Microsoft site:
http://msdn.microsoft.com/en-us/library/ms179215(v=sql.105).aspx
Here is a more general discussion of a sequence in Xquery.
http://en.wikibooks.org/wiki/XQuery/Sequences
I realize that my original answer above is incorrect after reading the page on the Microsoft site I referred to above. That page says that you need a comma between elements to construct a sequence. The example given is not a "sequence". However, my original info about changing the sort order stands :)
I think that same rules of Select apply here, no matter if you're selectig from ordinary table, or XML. There's selection part, and there's projection part, and the engine can take different paths to retrieve your data (from the middle sideways, for example). Unfortunately I can't find any official document to support that.
And for sure, there's no intrinsic table/document order that you can access and manipulate.
You can add order by clause to the select statement.
DECLARE #x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>'SELECT [column1] = t.i.value('.', 'int') FROM #x.nodes('/hey/#i') t(i) order by column1 desc
I know what you mean about this. I suspect the order would be document order, but the documentation does not make it clear, and relying on it implicitly just isn't nice.
One way to be confident about the order would be:
DECLARE #x XML = '<hey i="3"/><hey i="4"/><hey i="0"/>';
select #x.value('(/hey[sql:column("id")]/#i)[1]', 'int'), id
from (
select row_number() over (order by (select 0)) as id
from #x.nodes('/hey') t(i)
) t
order by id
This would then give you a way to answer your other question, i.e. getting the values in reverse, or some other, order.
N.B. This is going to be much slower than just using nodes as the size of your XML increases.
What is the advantage of using select clause in the from clause over normal select clause ?. For ex.
select name, age, address from emp where
empid = 12.
what is the advantage of below query over above query.
select A.name, A.age, A.address from (select
* from emp where empid = 12) as A.
The inner query creates a temp view and from that result, the fields in the first query selected. Right ?. But the query mentioned in the top of this question can also be used to get the same result.
What is the advantage? Thanks.
One way this technique can be used to derive results in the inner query that you don't want presented in the outer query. A simple example, I want to see the oldest person in each household, here is one way to do it:
SELECT name, age, address FROM
(
SELECT name, age, address,
rn = ROW_NUMBER() OVER (PARTITION BY address ORDER BY age DESC)
FROM dbo.emp
) AS x
WHERE rn = 1;
This way the derived column (a ranking, essentially, of household members by age, oldest first) does not need to be a column in the result set (and this also makes it convenient for filtering).
And I'm sure there are plenty of others (such as not having to repeat elaborate expressions); this was just the first one that came to mind.
In the case you posted in your question, I don't see an advantage at all. If you post a real example, where someone said there was an advantage, we might be able to explain why (or at least why they may have thought that).
This seems like an easy thing, but I'm drawing a blank.
Select * from
....
inner join
(
select JobsID, Value from Jobs where Value **is the highest**
) as MaxJob on MaxJob.CustID = A.CustID
inner join
(
select other information based upon MaxJob.JobID
) as OtherStuff
Is there a nice way to have that first subquery give me the Job ID of the job with the maximum Value?
Thanks... this seems easy and I'm sure I'm overlooking something very elementary. One of those days...
Edit: Due to this question being a bit ambiguous, I've written up a much more detailed question here (since this question was answered correctly).
If you want the single JobId with the highest Value:
SELECT JobId FROM Jobs WHERE Value = SELECT MAX(Value) FROM Jobs
But, that may give you multiple JobIds if thay all have the same Value. So, assuming you don't want that, I'd probably do:
SELECT MAX(JobId) as JobId FROM Jobs WHERE Value = SELECT MAX(Value) FROM Jobs
Select top 1 JobId, Value from Jobs order by Value desc
This may result in a worse performance than max(Value), but it is less code
Yes, you're overlooking something: the excellent new language features in SQL Server 2005 and later! Particularly the analytic functions like row_number() and the very cool CROSS APPLY join.
row_number solves the first question (choosing "the highest" something for a given other thing):
with Ranked(a,b,c,d,rk) as (
select T1.a,T2.b,T2.c,T2.d,
row_number() over (
partition by T1.a
order by T2.x desc
)
from T1 join T2 on someCondition
)
select a,b,c,d
from Ranked
where rk = 1;
CROSS APPLY solves the second question - creating a table source "based on MaxJob.JobID":
select *
from tableOrJoin
cross apply (
select stuff
from elsewhere
where something = tableOrJoin.JobID
) as A
In other words, it allows you to have a "correlated join" by using a column value from the left hand table source in the definition of the right-hand table source.
If you have a specific question, please give more specific information. I suspect you may be able to use both of these new features in your solution.
select max(JobId), value from jobs where...
Edit: my bad I misread the question, this might work
select jobid, max(value) from jobs....
SELECT j.JOBID, MAX(Value) OVER(order by j.Value PARTITION by j.JOBID) as max_val, s.foobar
FROM Jobs j
INNER JOIN SomeOtherTable s ON (s.jobid = j.jobid)
WHERE booya = win
I suspect that might make no sense, cause I don't know your tables :D
But LEARN THE POWER OF OVER AND PARTITION. LEARN IT, LOVE IT.
I have a simple query that runs in SQL 2008 and uses a custom CLR aggregate function, dbo.string_concat which aggregates a collection of strings.
I require the comments ordered sequentially hence the ORDER BY requirement.
The query I have has an awful TOP statement in it to allow ORDER BY to work for the aggregate function otherwise the comments will be in no particular order when they are concatenated by the function.
Here's the current query:
SELECT ID, dbo.string_concat(Comment)
FROM (
SELECT TOP 10000000000000 ID, Comment, CommentDate
FROM Comments
ORDER BY ID, CommentDate DESC
) x
GROUP BY ID
Is there a more elegant way to rewrite this statement?
So... what you want is comments concatenated in order of ID then CommentDate of the most recent comment?
Couldn't you just do
SELECT ID, dbo.string_concat(Comment)
FROM Comments
GROUP BY ID
ORDER BY ID, MAX(CommentDate) DESC
Edit: Misunderstood your objective. Best I can come up with is that you could clean up your query a fair bit by making it SELECT TOP 100 PERCENT, it's still using a top but at least it gets around having an arbitrary number as the limit.
Since you're using sql server 2008, you can use a Common Table Expression:
WITH cte_ordered (ID, Comment, CommentDate)
AS
(
SELECT ID, Comment, CommentDate
FROM Comments
ORDER BY ID, CommentDate DESC
)
SELECT ID, dbo.string_concat(Comment)
FROM cte_ordered
GROUP BY ID