SQLite - sql question 101 - sql

I would do something like this:
select * from cars_table where body not equal to null.
select * from cars_table where values not equal to null And id = "3"
I know the syntax for 'not equal' is <>, but I get an empty results.
For the second part, I want to get a result set where it only returns the columns that have a value. So, if the value is null, then don't include that column.
Thanks

You cannot use equality operators for nulls, you must use is null and is not null.
So your first query would be:
select * from cars_table where body is not null;
There's no easy way to do your second operation (excluding columns that are null). I'm assuming you mean don't display the column if all rows have NULL for that column, since it would be even harder to do this on a row-by-row basis. A select statement expects a list of columns to show, and will faithfully show them whether they are null or not.
The only possibility that springs to mind is a series (one per column) of selects with grouping to determine if the column only has nulls, then dynamically construct a new query with only columns that didn't meet that criteria.
But that's incredibly messy and not at all suited to SQL - perhaps if you could tell us the rationale behind the request, there may be another solution.

Comparing to NULL is not done with <>, but with is null and is not null :
select *
from cars_table
where body is not null
And :
select *
from cars_table
where values is not null
and id = '3'
NULL is not a normal value, and has to be dealt with differently than standard values.

In SQL, NULL is an unknown value. It is neither equal-to nor not-equal-to any other value. All comparison operators (=, <>, <, >, etc.) return false if either of the values being compared is NULL. (I don't know how old you are, so I can't say that you're 24, but I also can't say that you're not 24.)
As already mentioned, you have to use IS NULL or IS NOT NULL instead when testing for NULL values.

Thank you all for your answers.
Well, I have a table with a bunch of columns.
And I am going to search a particular car, and get the values for that car...
car | manual | automatic | sedan | power brakes | jet engine
honda | true | false | false | true | false
mazda | false | true | false | true | true
So, I want to do ->
select * from car_table where car='mazda' and values not equal to false
So then I just iterate over the cursor result and fill up the table with the appropriate columns and values. Where values are columns. I guess I replace values with * for columns
I know I could do it programmatically, but was thinking I could do this just by sql

Related

how to add filter on output of sql query to get answer as boolean?

I have one table in which ids are mentioned and values for that id.
id | value
101 | admin
102 | user
103 | test
104 | admin
105 | basic
I get input as 2 ids. now, I have to check whether these two ids have equal value or not? This id field is foreign key in some other table.
so far I tried this:
select id, value from roles where id in('101', '104')
but I want output to be as - not equal or equal or return some value only if equal, empty output if not equal.
Note: values will be never be null
I am using oracle 12 and node.js.
Here is one way.
select case when min(value) = max(value) then 'equal' else 'not equal' end
as compare_values
from roles
where id in ('101', '104')
;
This works even if you pass three or more id's - it just tells you if ALL the values (for ALL the id's) are equal.
Note that if value can be null (you said that's not the case in your real-life data), the null values will be ignored; the query will return 'equal' if all non-null values are equal.

SQL - concatenate values in columns but keep only first non-null value

I have the following table in Postgresql. The first 4 records are the base data and the others were generated with the ROLLUP function.
I want to add a column "grp_1" that will display the first non-null value of the columns grp1_l1, grp2_l2 and grp2_l3
I can get to the desired result by nesting 3 "case" functions using the SQL below, but my real table has 4 groups with each 8 to 10 columns (so a lot of nested "case" function).
sql:
SELECT grp1_l1, grp1_l2, grp1_l3, case when grp1_l1 is not null then grp1_l1 else case when grp1_l2 is not null then grp1_l2 else case when grp1_l3 is not null then grp1_l3 else null end end end as grp1, value
FROM public.query_test;
Is there a better and more scalable to handle this requirement ? Any suggestions are welcome.
The id will not always have 3 digits, that is just the case in my example here
Use coalesce() it's defined as "returns the first of its arguments that is not null" - which is exactly what you want.
coalesce(grp1_l1, grp1_l2, grp1_l3)

How to get all combinations (ordered sampling without replacement) in regex

I'm trying to match a comma-separated string of numbers to a certain pattern within an sql query. I used regular expressions for similar problems in the past successfully, so I'm trying to get them working here as well. The problem is as follows:
The string may contain any number in a range (e.g. 1-4) exactly 0-1 times.
Two numbers are comma-separated
The numbers have to be in ascending order
(I think this is kind of a case of ordered sampling without replacement)
Sticking with the example of 1-4, the following entries should match:
1
1,2
1,3
1,4
1,2,3
1,2,4
1,3,4
1,2,3,4
2
2,3
2,4
3
3,4
4
and these should not:
q dawda 323123 a3 a1 1aa,1234 4321 a4,32,1a 1112222334411
1,,2,33,444, 11,12,a 234 2,2,3 33 3,3,3 3,34 34 123 1,4,4,4a 1,444
The best try I currently have is:
\b[1-4][\,]?[2-4]?[\,]?[3-4]?[\,]?[4]?\b
This still has two major drawbacks:
It delivers quite a lot of false positives. Numbers are not eliminated after they occurred once.
It will get rather long, when the range of numbers increases, e.g. 1-18 is already possible as well, bigger ranges are thinkable of.
I used regexpal for testing purposes.
Side notes:
As I'm using sql it would be possible to implement some algorithm in another language to generate all the possible combinations and save them in a table that can be used for joining, see e.g. How to get all possible combinations of a list’s elements?. I would like to only rely on that as a last resort, as the creation of new tables will be involved and these will contain a lot of entries.
The resulting sql statement that uses the regex should run on both Postgres and Oracle.
The set of positive examples is also referred to as "powerset".
Edit: Clarified the list of positive examples
I wouldn't use Regex for this, as e.g. the requirements "have to be unique" and "have to be in ascending order" can't really be expressed with a regular expression (at least I can't think of a way to do that).
As you also need to have an expression that is identical in Postgres and Oracle, I would create a function that checks such a list and then hide the DBMS specific implementation in that function.
For Postgres I would use its array handling features to implement that function:
create or replace function is_valid(p_input text)
returns boolean
as
$$
select coalesce(array_agg(x order by x) = string_to_array(p_input, ','), false)
from (
select distinct x
from unnest(string_to_array(p_input,',')) as t(x)
where x ~ '^[0-9]+$' -- only numbers
) t
where x::int between 1 and 4 -- the cast is safe as the inner query only returns valid numbers
$$
language sql;
The inner query returns all (distinct) elements from the input list as individual numbers. The outer query then aggregates that back for values in the desired range and numeric order. If that result isn't the same as the input, the input isn't valid.
Then with the following sample data:
with sample_data (input) as (
values
('1'),
('1,2'),
('1,3'),
('1,4'),
('1,2,3'),
('1,2,4'),
('foo'),
('1aa,1234'),
('1,,2,33,444,')
)
select input, is_valid(input)
from sample_data;
It will return:
input | is_valid
-------------+---------
1 | true
1,2 | true
1,3 | true
1,4 | true
1,2,3 | true
1,2,4 | true
foo | false
1aa,1234 | false
1,,2,33,444, | false
If you want to use the same function in Postgres and Oracle you probably need to use returns integer in Postgres as Oracle still doesn't support a boolean data type in SQL
Oracle's string processing functions are less powerful than Postgres' functions (e.g. no string_to_array or unnest), but you can probably implement a similar logic in PL/SQL as well (albeit more complicated)

PostgreSQL: order by column, with specific NON-NULL value LAST

When I discovered NULLS LAST, I kinda hoped it could be generalised to 'X LAST' in a CASE statement in the ORDER BY portion of a query.
Not so, it would seem.
I'm trying to sort a table by two columns (easy), but get the output in a specific order (easy), with one specific value of one column to appear last (got it done... ugly).
Let's say that the columns are zone and status (don't blame me for naming a column zone - I didn't name them). status only takes 2 values ('U' and 'S'), whereas zone can take any of about 100 values.
One subset of zone's values is (in pseudo-regexp) IN[0-7]Z, and those are first in the result. That's easy to do with a CASE.
zone can also take the value 'Future', which should appear LAST in the result.
In my typical kludgy-munge way, I have simply imposed a CASE value of 1000 as follows:
group by zone, status
order by (
case when zone='IN1Z' then 1
when zone='IN2Z' then 2
when zone='IN3Z' then 3
.
. -- other IN[X]Z etc
.
when zone = 'Future' then 1000
else 11 -- [number of defined cases +1]
end), zone, status
This works, but it's obviously a kludge, and I wonder if there might be one-liner doing the same.
Is there a cleaner way to achieve the same result?
Postgres allows boolean values in the ORDER BY clause, so here is your generalised 'X LAST':
ORDER BY (my_column = 'X')
The expression evaluates to boolean, resulting values sort this way:
FALSE (0)
TRUE (1)
NULL
Since we deal with non-null values, that's all we need. Here is your one-liner:
...
ORDER BY (zone = 'Future'), zone, status;
Related:
Sorting null values after all others, except special
Select query but show the result from record number 3
SQL two criteria from one group-by
I'm not familiar postgreSQL specifically, but I've worked with similar problems in MS SQL server. As far as I know, the only "nice" way to solve a problem like this is to create a separate table of zone values and assign each one a sort sequence.
For example, let's call the table ZoneSequence:
Zone | Sequence
------ | --------
IN1Z | 1
IN2Z | 2
IN3Z | 3
Future | 1000
And so on. Then you simply join ZoneSequence into your query, and sort by the Sequence column (make sure to add good indexes!).
The good thing about this method is that it's easy to maintain when new zone codes are created, as they likely will be.

How to use a where statement that does not ignore Nulls in Big Query

I was a little surprised to find out that the WHERE statement in Google Big Query ignores NULLS. Does anyone know of a better way to do this?
I have the following data set:
Name Score
Allan 20
Brian NULL
Clare 30
Say I want to select all records where the Score is not equal to 20. If I use the following code in Big Query
SELECT * FROM [....]
where
Score <> 20
The following is the result:
Name Score
Clare 30
The problem is that the record for Brian which is NULL is also not equal to 20 and therefore should be in my results.
Other than checking spefically for NULLS is there a better way to do this?
Thanks
Ria
SQL (and thus BigQuery, which is SQL-like), has a trivalent logic. What that boils down to is that statements cannot just be TRUE or FALSE, they can also be NULL. In this case, the statement NULL <> 20 is neither TRUE nor FALSE, it is itself NULL. It might be helpful to think of NULL values as unknown. Since we don't know Brian's age, we don't know whether it is equal to 20. But the query only returns rows for which the where-clause evaluates to TRUE, and therefore the row with Brian is excluded.
If you want to include NULL values, you have to explicitly write
where (Score <> 20 or Score is null)
select * from [...]
where coalesce(score, 0) <> 20
One more variant:
SELECT * FROM [...]
WHERE ifnull(score <> 20, true)
I kind of like it as a way to express "accept either TRUE or NULL boolean values from this expression; reject FALSE."
How you can achieve by-
SELECT * FROM [....]
where
Score <> 20 or Scrore is NULL
Is there any efficient way-
To avoid this performance killing way, we should keep column property as not null.