In SQL, does a BETWEEN statement have to be of the form BETWEEN lowest AND highest? - sql

For example, if I did:
SELECT * FROM Users WHERE UserId BETWEEN 100 AND 1
what would the results be?
Edit: Sorry, you're right, I should have specified. I didn't want to know the exact number of rows that would return, I just wanted to know if it would return rows that were between 1 and 100 or if it would return rows from min(UserId) to 1 and 100 to max(UserId).

a BETWEEN b AND c
is shorthand for
b <= a and a <= c
So BETWEEN 100 and 1 won't match anything.

This probably depends on your RDBMS, but why not just try it out? On MySQL, I get no rows from a BETWEEN 100 AND 1 query whereas I do get rows from asking for BETWEEN 1 and 100.

Related

Filtering a column based on having some value in one of the rows in SQL or Presto Athena

I am trying in Athena to output only users which have some specific value in them but not in all of the rows
Suppose I have the table below.
I want all users which have value '100' in at least one of their rows but also having in other rows value different than 100.
user | value
A | 1
B | 2
A | 100
D | 3
A | 4
C | 3
C | 5
D | 100
So in this example I would want to get only users A and D because only them having 100 and none 100.
I tried maybe grouping by user and creating an array of values per user and then checking if array contains 100 but I don't manage doing it presto.
Also I thought about converting rows to columns and then checking if one of columns equals 100.
Those solutions are too complex? Anybody knows how to implement them or anyone has a better simpler solution?
The users that have at least one value of 100 can be found with this SQL:
SELECT DISTINCT user
FROM some_table
WHERE value = 100
But I assume you are after all tuples of user and value where the user has at least one value of 100, this can be accomplished by using the query above in a slightly more complex query:
WITH matching_users AS (
SELECT DISTINCT user
FROM some_table
WHERE value = 100
)
SELECT user, value
FROM matching_users
LEFT JOIN some_table USING (user)
You can use sub query as below to achieve your required output=
SELECT * FROM your_table
WHERE User IN(
SELECT DISTINCT User
FROM your_table
WHERE Value = 100
)
If you just want the users, I would go for aggregation:
select user
from t
group by user
having sum(case when value = 100 then 1 else 0 end) > 0;
If 100 is the maximum possible value, this can be simplified to:
having max(value) = 100

ORDER BY followed by a number

I took this query from this question.
SELECT *
FROM A
WHERE x='abc'
OR y=0
order by case when x='abc' then 0 else 1 end;
This query supposedly will prioritize x='abc' cases. But I'm really confused why is this happening? Isn't ORDER BY followed by a column name or column number? Also, I researched on the syntax of ORDER BY and they don't tell anything about this. I also tried something like this but it says: "1st ORDER BY term out of range - should be between 1 and 1":
SELECT A
FROM B
ORDER BY 2
So, can anyone explain this query or at least point to a good documentation? Thank you very much.
Well, when an ORDER BY clause is followed by a number, this number will be referenced to the column in the (number) position.
The ORDER BY followed by a CASE EXPRESSION is called conditional ordering, each column will get the value 0 when x is equal to abc and when its not it will get the value 1. After that, the ordering is in ASC , so 0 will always be prioitized before 1.
It will be something like this:
x | y | .... | Here is the new value that will order the query
abc 1 0
ayr 0 1
acz 1 1
.........
So, basically it's like generating a new value.

In VBA Excel through ADO SQL, How may I refer to a record "only once" and link it to another avoiding the same record to be recalled?

I have a table with 3 fields:
(the quantity are positive and negative)
TAB_A
ID | quantity | Related_ID
1 100 *? (It is 2 and it is correct)
2 -100 (nothing)
3 100 *? (It is 2 but it should be 4)
4 -100 (nothing)
and the following SQL query:
UPDATE Table_A AS ta LEFT JOIN Table_A AS tb ON ta.[quantity] = -tb.[quantity]
SET ta.Related_ID = tb.[ID]
WHERE ta.[quantity] > 0 AND tb.[Quantity] < 0
I would like to add to the query a part that recognizes the ID already used and won't use them a second time.
Something like this might help, depending on whether all your data is like the sample you posted.
query from question
and tb.id =
(select min(id)
from table_a
where id > ta.id)
The syntax might not be 100% correct but the logic should be ok. Test this by changing your update query to a select query and look at the results.
This solution is in line with my question but I do not think if it is able to cover all the cases. The initial results can be also listed as follow:
-100
-90
-100
100
90
100
The quantity could be listed in any order randomly.

Display more than one row with the same result from a field

I need to show more than one result from each field in a table. I need to do this with only one SQL sentence, I donĀ“t want to use a Cursor.
This seems silly, but the number of rows may vary for each item. I need this to print afterwards this information as a Crystal Report detail.
Suppose I have this table:
idItem Cantidad <more fields>
-------- -----------
1000 3
2000 2
3000 5
4000 1
I need this result, using one only SQL Sentence:
1000
1000
1000
2000
2000
3000
3000
3000
3000
3000
4000
where each idItem has Cantidad rows.
Any ideas?
It seems like something that should be handled in the UI (or the report). I don't know Crystal Reports well enough to make a suggestion there. If you really, truly need to do it in SQL, then you can use a Numbers table (or something similar):
SELECT
idItem
FROM
Some_Table ST
INNER JOIN Numbers N ON
N.number > 0 AND
N.number <= ST.cantidad
You can replace the Numbers table with a subquery or function or whatever other method you want to generate a result set of numbers that is at least large enough to cover your largest cantidad.
Check out UNPIVOT (MSDN)
Another example
If you use a "numbers" table that is useful for this and many similar purposes, you can use the following SQL:
select t.idItem
from myTable t
join numbers n on n.num between 1 and t.Cantidad
order by t.idTtem
The numbers table should just contain all integer numbers from 0 or 1 up to a number big enough so that Cantidad never exceeds it.
As others have said, you need a Numbers or Tally table which is just a sequential list of integers. However, if you knew that Cantidad was never going to be larger than five for example, you can do something like:
Select idItem
From Table
Join (
Select 1 As Value
Union All Select 2
Union All Select 3
Union All Select 4
Union All Select 5
) As Numbers
On Numbers.Value <= Table.Cantidad
If you are using SQL Server 2005, you can use a CTE to do:
With Numbers As
(
Select 1 As Value
Union All
Select N.Value + 1
From Numbers As N
)
Select idItem
From Table
Join Numbers As N
On N.Value <= Table.Cantidad
Option (MaxRecursion 0);

How do I limit the number of records returned for Interbase 7.1?

We have an Interbase 7.1 database and I'm trying to figure out how to limit the number of records returned by the query to just 1. I really only need to know an event code from the last record, in which the query will return hundreds of records if I cannot do some kind of limit.
Thanks in advance!
I think I figured it out. Needed to do something like this...
SELECT * FROM table ORDER BY col ROWS 1
As per the accepted answer:
SELECT * FROM table ORDER BY col ROWS 1
Will return just one result.
There are also several other row limiting options available:
ROWS n Returns the first n rows of the result set, or n percent if used with PERCENT
ROWS m TO n Returns rows m through n, inclusive or the mth to nth percent
ROWS n BY p Returns every pth row of the first n rows
This is particularly handy for paged results.
From the Embedded SQL Guide on the InterBase Product Documentation page: