T-SQL to find rows with given number of digits - tsql

I need to select rows where a column (that is varchar) contains 10 or more digits (any) in a row.
'115555711111' - true
'abc11143555111111def' - true
'000345345500abc' - true
'1411a6551a111' - false
This does not work:
SELECT * FROM Table WHERE PATINDEX('%[0-9]{10}%', Column1) > 0

SELECT *
FROM Table
WHERE Column1 LIKE '%' + REPLICATE('[0-9]',10) + '%'

Related

SELECT returns multiple answers

I have names table with columns id, name and last_name. So what i'm trying to do is select random name and last_name from it, i tried this:
SELECT (SELECT name FROM names WHERE ID =floor(random()* 18 + 1 + x - x)),
(SELECT last_name FROM names WHERE ID = floor(random()* 18 + 1 + x - x))
FROM GENERATE_SERIES(1, 100) as x;
But it says it returns more than one row, why and how can i fix it?
When you use your query it will generate random id for each row. Therefore it get match with multiple rows in name table. Therefore it return multiple rows for this part SELECT name FROM names WHERE ID =floor(random()* 18 + 1 + x - x)). SQL not allow more than one row to get select.
This will work. I think this is what you want.
SELECT (SELECT name FROM names WHERE ID =(select floor(random()* 18 + 1 + x - x))) ,
(SELECT last_name FROM scientist WHERE id = (select floor(random()* 18 + 1 + x - x))) FROM GENERATE_SERIES(1, 100) as x;
The volatile random() function will generate a different value for each row of your table, so none or more than one row could be selected. You can avoid that by putting random() into an uncorrelated subquery, then it will only be executed once:
SELECT name FROM names
WHERE id = floor((SELECT random())*18 + 1);

SQL - How do I select only the decimal numbers that only have zero after the semicolon?

i have column Val:
2.32
1234.54
1234.00
1234.5456
1234.54567
and i want only select number like 1234.00
thanks in advance for help
Select * from mytable where (Round(val,0) - val) = 0
or if you want to 2 decimal places I think this will work
Select * from mytable where (Val - Round(val,2) < .001)

How to select rows where the condition where all rows are being extracted for a given condition?

I have this table
CREATE TABLE fruits
(
id SERIAL,
name VARCHAR
);
with these entries
INSERT INTO fruits(name)
VALUES('Orange');
INSERT INTO fruits(name)
VALUES('Ananas');
INSERT INTO fruits(name)
VALUES(null);
When I try to to select all rows that not equal to 'Ananas' by querying
select *
from fruits
where name <> 'Ananas'
I get these rows:
id name
-----------
1 Orange
What I would have expected was this
id name
-----------
1 Orange
3 null
How do I ensure that all rows that fulfills the condition gets selected?
Example in dbfiddle:
https://dbfiddle.uk/?rdbms=postgres_11&fiddle=a963d39df0466701b0a96b20db8461e6
Any "normal" comparison with null yields "unknown" which is treated as false in the context of the WHERE clause.
You need to use the null safe operator is distinct from:
select *
from fruits
where name is distinct from 'Ananas';
Alternatively you could convert NULL values to something different:
select *
from fruits
where coalesce(name, '') <> 'Ananas';

postgresql: How to grab an existing id from a not subsequent ids of a table

Postgresql version 9.4
I have a table with an integer column, which has a number of integers with some gaps, like the sample below; I'm trying to get an existing id from the column at random with the following query, but it returns NULL occasionally:
CREATE TABLE
IF NOT EXISTS test_tbl(
id INTEGER);
INSERT INTO test_tbl
VALUES (10),
(13),
(14),
(16),
(18),
(20);
-------------------------------
SELECT * FROM test_tbl;
-------------------------------
SELECT COALESCE(tmp.id, 20) AS classification_id
FROM (
SELECT tt.id,
row_number() over(
ORDER BY tt.id) AS row_num
FROM test_tbl tt
) tmp
WHERE tmp.row_num =floor(random() * 10);
Please let me know where I'm doing wrong.
but it returns NULL occasionally
and I must add to this that it sometimes returns more than 1 rows, right?
in your sample data there are 6 rows, so the column row_num will have a value from 1 to 6.
This:
floor(random() * 10)
creates a random number from 0 up to 0.9999...
You should use:
floor(random() * 6 + 1)::int
to get a random integer from 1 to 6.
But this would not solve the problem, because the WHERE clause is executed once for each row, so there is a case that row_num will never match the created random number, so it will return nothing, or it will match more than once so it will return more than 1 rows.
See the demo.
The proper (although sometimes not the most efficient) way to get a random row is:
SELECT id FROM test_tbl ORDER BY random() LIMIT 1
Also check other links from SO, like:
quick random row selection in Postgres
You could select one row and order by random(), this way you are ensured to hit an existing row
select id
from test_tbl
order by random()
LIMIT 1;

PostgreSQL Crosstab issues / "Return and SQL tuple descriptions are incompatible"

Good afternoon, I am using POSTGRESql version 9.2 and I'm trying to use a crosstab function to transpose two columns on a table so that i can later join it to a different SELECT query.
I have installed the tablefunc extension.
However i keep getting this "Return and SQL tuple descriptions are incompatible" error which seems to be because of typecasts.
I don't need them to be a specific type.
My original SELECT query is this
SELECT inventoryid, ttype, tamount
FROM inventorytesting
Which gives me the following result:
inventoryid ttype tamount
2451530088940460 7 0.2
2451530088940460 2 0.5
2451530088940460 8 0.1
2451530088940460 1 15.7
8751530077940461 7 0.7
8751530077940461 2 0.2
8751530077940461 8 1.1
8751530077940461 1 19.2
and my goal is to get it like:
inventoryid 7 2 8 1
8751530077940461 0.7 0.2 1.1 19.2
2451530088940460 0.2 0.5 0.1 15.7
The 'ttype' field has 49 different values such as "7","2","8","1" which are fixed.
The 'tamount' field varies its values depending on the 'inventoryid' field but there will always be 49 of them, even if its value is zero. It will never be "null".
I have tried a few variations that i could find in the internet which sum up to this:
SELECT *
FROM crosstab (
$$SELECT inventoryid, ttype, tamount
FROM inventorytesting
WHERE inventoryid = '2451530088940460'
ORDER BY inventoryid, ttype$$
)
AS ct("inventoryid" text,"ttype" smallint,"tamount" numeric)
The fieldtypes on the inventorytesting table are
select column_name, data_type from information_schema.columns
where table_name = 'inventorytesting'
Results:
column_name data_type
id bigint
ttype smallint
tamount numeric
tunit text
tlessthan smallint
plantid text
sessiontime bigint
deleted smallint
inventoryid text
docdata text
docname text
labid bigint
Any pointers would be great.
demo:db<>fiddle
The resulting table definition has to contain the table structure you are expecting - the pivoted one - and not the structure of the given one:
SELECT *
FROM crosstab(
$$SELECT inventoryid, ttype, tamount
FROM inventorytesting
WHERE inventoryid = '2451530088940460'
ORDER BY inventoryid, ttype$$
)
AS ct("inventoryid" text,"type1" numeric,"type2" numeric,"type7" numeric,"type8" numeric)
Addionally there is no need to use the crosstab function. You can achieve a pivot by simply using the standard CASE function:
SELECT
inventoryid,
SUM(CASE WHEN ttype = 1 THEN tamount END) AS type1,
SUM(CASE WHEN ttype = 2 THEN tamount END) AS type2,
SUM(CASE WHEN ttype = 7 THEN tamount END) AS type7,
SUM(CASE WHEN ttype = 8 THEN tamount END) AS type8
FROM
inventorytesting
GROUP BY 1
If you were on 9.4 or higher you could use the Postgres specific FILTER clause:
SELECT
inventoryid,
SUM(tamount) FILTER (WHERE ttype = 1) AS type1,
SUM(tamount) FILTER (WHERE ttype = 2) AS type2,
SUM(tamount) FILTER (WHERE ttype = 7) AS type7,
SUM(tamount) FILTER (WHERE ttype = 8) AS type8
FROM
inventorytesting
GROUP BY 1
demo:db<>fiddle
With the crosstab, you define the actual result table (basically the result of the pivot). The input query defines three columns which are then processed as:
grouping column result in the actual rows
the pivot columns
value for the pivot column
In your case, the crosstab therefore needs to be defined as:
ct(
"inventoryid" text,
"tamount_1" numeric,
"tamount_2" numeric,
"tamount_3" numeric,
...
)
The column header will then correlate to a certain value of column ttype in the order as defined by the inner query's ORDER BY.
The thing with crosstab is that missing values for ttype (e.g. some value returned for 4 but not for 3), the resulting columns would be 1, 2, 4, ... with 3 being missing. Here, you'd have to make sure (if you need consistent output) that your inner query returns at least a NULL row (e.g. via LEFT JOIN).