Select * with result columns that only contain values - postgresql

postgresql
--I don't want to have to enter each repeating column, I want syntax in the where clause that checks all the columns and returns only columns with data
SELECT *
FROM table_with_200_columns
where datetime between '2021-01-01' and current_date
and column.1 is not null
and column.1 <>''
and column.2 is not null
and column.2 <>''
and column.3-200 is not null
and column.3-200 <>''
;
--something like this with an "presently unknown function" as in the example of 'allofthemtherecolumns'
SELECT *
FROM table_with_200_columns
where datetime between '2021-12-01' and current_date
and allofthemtherecolumns is not null
and allofthemtherecolumns <>''
your assistance is greatly appreciated

You can transform a row into an hstore record, then extract just the values and look if none of them is null
select * from t
where false = ALL (SELECT unnest(avals(hstore(t))) IS NULL);
PS: you would need the hstore extension

Convert the table row to json, remove datetime and all null/blank valued key, then check it's not empty:
select *
from table_with_200_columns
where datetime between '2021-01-01' and current_date
and regexp_replace(jsonb_strip_nulls(to_jsonb(table_with_200_columns) - 'datetime')::text, '"[^"]+":"",?', '', 'g') != '{}'

Related

postgresql filter users by age range

Is there a better way of doing this?
Basically, I have a users table, and on of the columns is birth_date (date)
I am supposed to filter by age range, meaning, I will get a range like 18-24.
This will be passed to a function in a jsonb parameter, as an array of 2 integers.
So I have done the following
create or replace function my_filter_function(
p_search_parameters jsonb
)
returns TABLE(
user_id bigint,
birth_date date,
age interval,
years double precision
)
security definer
language plpgsql
as
$$
begin
return query
select u.user_id, u.birth_date, age(u.birth_date), date_part('year', age(u.birth_date))
from users u
where u.birth_date is not null
and ( (p_search_parameters#>>'{age,0}') is null or u.birth_date <= (now() - ((p_search_parameters#>>'{age,0}')::integer * interval '1 year'))::date)
and ( (p_search_parameters#>>'{age,1}') is null or u.birth_date >= (now() - ((p_search_parameters#>>'{age,1}')::integer * interval '1 year'))::date)
;
end;
$$;
-- this is just a aluttle helpder function to better post and explain the question
This seems to be doing the job, but was hoping to find other ways of doing this while still getting a jsonb parameter, array of 2 integers
Any ideas?

Use WHERE clause along with Between and NULL parameter for 2 date fields

Working with Parameters and SQL in a SSRS report
#FromDate and #ToDate can be null -- To get all 4 records
#Fromdate can have a date value while #ToDate is null - if this is the case need to get all date value which does not have TravelTo Date
#Fromdate and #todate has values then need to get the last 2 records
#FromDate and #ToDate is null then need to get all value
I used the below code to get the data but i am not getting the right data ,any suggestion is appreciated.
Where
(TravelTo BETWEEN #FROMSTART AND #TODATE)
or(#TODATE IS NULL and TravelFrom >=#FROMSTART )
OR(#FROMSTART IS NULL AND TravelFrom <=#TODATE)
OR(#FROMSTART IS NULL AND #TODATE IS NULL)
Parmater screenshot from SSRS
Assuming the either the date inputs or the columns themselves could be NULL, you may try:
SELECT *
FROM yourTable
WHERE
(#FROMSTART > TravelFrom OR #FROMSTART IS NULL OR TravelFrom IS NULL) AND
(#TODATE < TravelTo OR #TODATE IS NULL OR TravelTo IS NULL);
This logic would discount either the start or end of the date range should either the column have a NULL value, or the input have a NULL value.
SELECT *
FROM TABLE1
WHERE ((#FROMSTART IS NULL AND #TODATE IS NULL)
OR(#FROMSTART IS NULL AND TravelTo <=#TODATE)
OR(#TODATE IS NULL AND TravelFrom >=#FROMSTART)
OR(TravelFrom >= #FROMSTART AND TravelTo<=#TODATE))
Hope this Query Works fine for your case:
You had forgot to mentioned these conditions within an Open/Close bracket.So that only you cannot get the right output.
I think the problem is the 2nd condition
#Fromdate can have a date value while #ToDate is null - if this is the case need to get all date value which does not have TravelTo Date
Please try the code below which does (I think) what you specified in your question. If this does not work, please supply a set of test dates and expected outcome for each test as some are a little ambiguous.
NOTE: I have used standard date format for the dates as these will not suffer from conversion to and from the MM/DD/YYYY format you are using.
DECLARE #t TABLE (ID int, TravelFrom date, TravelTo date)
INSERT INTO #t VALUES
(9759497, '2020-02-01', NULL),
(5226416, '2020-01-15', NULL),
(2731975, '2020-03-01', '2020-04-30'),
(2318260, '2020-01-01', '2020-02-28')
DECLARE #fromDate date = '2020-02-01'
DECLARE #toDate date = NULL
SELECT * FROM #t
WHERE
(TravelFrom >= #fromDate or #fromDate is null)
AND
(TravelTo <= #toDate or #toDate is null)
AND
(
CASE WHEN #toDate IS NULL THEN 1 ELSE 0 END
=
CASE WHEN TravelTo IS NULL THEN 1 ELSE 0 END
)

Postgresql: how to return a single column request as an integer array

I would like to create a function that returns a column of a table as an integer array.
In other words, how can I transfrom the result of SELECT id FROM mytable to integer[] ?
You can do:
SELECT ARRAY(SELECT id FROM mytable)
Or:
SELECT array_agg(id) FROM mytable

Extracting the number of days from a calculated interval

I am trying to get a query like the following one to work:
SELECT EXTRACT(DAY FROM INTERVAL to_date - from_date) FROM histories;
In the referenced table, to_date and from_date are of type timestamp without time zone. A regular query like
SELECT to_date - from_date FROM histories;
Gives me interval results such as '65 days 04:58:09.99'. But using this expression inside the first query gives me an error: invalid input syntax for type interval. I've tried various quotations and even nesting the query without luck. Can this be done?
SELECT EXTRACT(DAY FROM INTERVAL to_date - from_date) FROM histories;
This makes no sense. INTERVAL xxx is syntax for interval literals. So INTERVAL from_date is a syntax error, since from_date isn't a literal. If your code really looks more like INTERVAL '2012-02-01' then that's going to fail, because 2012-02-01 is not valid syntax for an INTERVAL.
The INTERVAL keyword here is just noise. I suspect you misunderstood an example from the documentation. Remove it and the expression will be fine.
I'm guessing you're trying to get the number of days between two dates represented as timestamp or timestamptz.
If so, either cast both to date:
SELECT to_date::date - from_date::date FROM histories;
or get the interval, then extract the day component:
SELECT extract(day from to_date - from_date) FROM histories;
This example demontrates the creation of a table with trigger which updates the difference between a stop_time and start_time in DDD HH24:MI:SS format where the DDD stands for the amount of dates ...
DROP TABLE IF EXISTS benchmarks ;
SELECT 'create the "benchmarks" table'
;
CREATE TABLE benchmarks (
guid UUID NOT NULL DEFAULT gen_random_uuid()
, id bigint UNIQUE NOT NULL DEFAULT cast (to_char(current_timestamp, 'YYMMDDHH12MISS') as bigint)
, git_hash char (8) NULL DEFAULT 'hash...'
, start_time timestamp NOT NULL DEFAULT DATE_TRUNC('second', NOW())
, stop_time timestamp NOT NULL DEFAULT DATE_TRUNC('second', NOW())
, diff_time varchar (20) NOT NULL DEFAULT 'HH:MI:SS'
, update_time timestamp DEFAULT DATE_TRUNC('second', NOW())
, CONSTRAINT pk_benchmarks_guid PRIMARY KEY (guid)
) WITH (
OIDS=FALSE
);
create unique index idx_uniq_benchmarks_id on benchmarks (id);
-- START trigger trg_benchmarks_upsrt_diff_time
-- hrt = human readable time
CREATE OR REPLACE FUNCTION fnc_benchmarks_upsrt_diff_time()
RETURNS TRIGGER
AS $$
BEGIN
-- NEW.diff_time = age(NEW.stop_time::timestamp-NEW.start_time::timestamp);
NEW.diff_time = to_char(NEW.stop_time-NEW.start_time, 'DDD HH24:MI:SS');
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trg_benchmarks_upsrt_diff_time
BEFORE INSERT OR UPDATE ON benchmarks
FOR EACH ROW EXECUTE PROCEDURE fnc_benchmarks_upsrt_diff_time();
--
-- STOP trigger trg_benchmarks_upsrt_diff_time
Just remove the keyword INTERVAL:
SELECT EXTRACT(DAY FROM to_date - from_date) FROM histories;

How to check if a date is in a list of dates - TSQL

I am trying to create a SQL query that checks if a date is in a list of dates but my query doesn't work...
SELECT *
FROM TABLE1
WHERE field1 = value1
AND convert(nvarchar(15),date_start,101) IN
(SELECT convert(nvarchar(15),date_end,101)
FROM TABLE2
)
This query should return some values but it doesn't...
do not convert the data i think there is no need for this
Try this :
SELECT *
FROM TABLE1
WHERE field1 = value1
AND date_start IN
(SELECT date_end FROM TABLE2)