Can't select an existing column in PostgreSQL - sql

I'm new in SQL and I'm trying to select column Foto_municipis:
askdbase4=# select * from avatar_avatarx;
id | llista_municipis | Foto_municipis | primary | date_uploaded
----+------------------+-----------------+---------+------------------------
1 | Tore | tore.jpg | t | 2014-06-05 01:19:40+02
2 | Calldetenes | calldetenes.jpg | f | 2014-06-05 23:24:18+02
3 | Rupit i Pruit | baixa.jpeg | f | 2014-06-16 03:09:48+02
4 | Olost | olost.jpg | f | 2014-06-16 23:20:05+02
(4 rows)
for some reason I can select llista municipis successfully:
SELECT llista_municipis FROM avatar_avatarx;
but when I try to select Foto_municipis this is what I get:
askdbase4=# SELECT llista_municipis FROM avatar_avatarx;
ERROR: column "Foto_municipis" does not exist
LINE 1: select Foto_municipis from avatar_avatarx;
What am I doing wrong?

You probably created the column with a double-quoted identifier and this will work:
select "Foto_municipis"
from avatar_avatarx
That is almost always a bad idea as it will be forever necessary to reference it using double-quotes, unless it is an all lower case identifier in which case it can be referenced in lower case without double quotes.
If the column is created with an identifier without double quotes then it is possible to reference it in any case style like Foto_municipis or foto_Municipis regardless of the original identifier case style.

Related

How to get a value inside of a JSON that is inside a column in a table in Oracle sql?

Suppose that I have a table named agents_timesheet that having a structure like this:
ID | name | health_check_record | date | clock_in | clock_out
---------------------------------------------------------------------------------------------------------
1 | AAA | {"mental":{"stress":"no", "depression":"no"}, | 6-Dec-2021 | 08:25:07 |
| | "physical":{"other_symptoms":"headache", "flu":"no"}} | | |
---------------------------------------------------------------------------------------------------------
2 | BBB | {"mental":{"stress":"no", "depression":"no"}, | 6-Dec-2021 | 08:26:12 |
| | "physical":{"other_symptoms":"no", "flu":"yes"}} | | |
---------------------------------------------------------------------------------------------------------
3 | CCC | {"mental":{"stress":"no", "depression":"severe"}, | 6-Dec-2021 | 08:27:12 |
| | "physical":{"other_symptoms":"cancer", "flu":"yes"}} | | |
Now I need to get all agents having flu at the day. As for getting the flu from a single JSON in Oracle SQL, I can already get it by this SQL statement:
SELECT * FROM JSON_TABLE(
'{"mental":{"stress":"no", "depression":"no"}, "physical":{"fever":"no", "flu":"yes"}}', '$'
COLUMNS (fever VARCHAR(2) PATH '$.physical.flu')
);
As for getting the values from the column health_check_record, I can get it by utilizing the SELECT statement.
But How to get the values of flu in the JSON in the health_check_record of that table?
Additional question
Based on the table, how can I retrieve full list of other_symptoms, then it will get me this kind of output:
ID | name | other_symptoms
-------------------------------
1 | AAA | headache
2 | BBB | no
3 | CCC | cancer
You can use JSON_EXISTS() function.
SELECT *
FROM agents_timesheet
WHERE JSON_EXISTS(health_check_record, '$.physical.flu == "yes"');
There is also "plain old way" without JSON parsing only treting column like a standard VARCHAR one. This way will not work in 100% of cases, but if you have the data in the same way like you described it might be sufficient.
SELECT *
FROM agents_timesheet
WHERE health_check_record LIKE '%"flu":"yes"%';
How to get the values of flu in the JSON in the health_check_record of that table?
From Oracle 12, to get the values you can use JSON_TABLE with a correlated CROSS JOIN to the table:
SELECT a.id,
a.name,
j.*,
a."DATE",
a.clock_in,
a.clock_out
FROM agents_timesheet a
CROSS JOIN JSON_TABLE(
a.health_check_record,
'$'
COLUMNS (
mental_stress VARCHAR2(3) PATH '$.mental.stress',
mental_depression VARCHAR2(3) PATH '$.mental.depression',
physical_fever VARCHAR2(3) PATH '$.physical.fever',
physical_flu VARCHAR2(3) PATH '$.physical.flu'
)
) j
WHERE physical_flu = 'yes';
db<>fiddle here
You can use "dot notation" to access data from a JSON column. Like this:
select "DATE", id, name
from agents_timesheet t
where t.health_check_record.physical.flu = 'yes'
;
DATE ID NAME
----------- --- ----
06-DEC-2021 2 BBB
Note that this approach requires that you use an alias for the table name (so you can use it in accessing the JSON data).
For testing I used the data posted by MT0 on dbfiddle. I am not a big fan of double-quoted column names; use something else for "DATE", such as dt or date_.

PostgreSQL Compare value from row to value in next row (different column)

I have a table of encounters called user_dates that is ordered by 'user' and 'start' like below. I want to create a column indicating whether an encounter was followed up by another encounter within 30 days. So basically I want to go row by row checking if "encounter_stop" is within 30 days of "encounter_start" in the following row (as long as the following row is the same user).
user | encounter_start | encounter_stop
A | 4-16-1989 | 4-20-1989
A | 4-24-1989 | 5-1-1989
A | 6-14-1993 | 6-27-1993
A | 12-24-1999 | 1-2-2000
A | 1-19-2000 | 1-24-2000
B | 2-2-2000 | 2-7-2000
B | 5-27-2001 | 6-4-2001
I want a table like this:
user | encounter_start | encounter_stop | subsequent_encounter_within_30_days
A | 4-16-1989 | 4-20-1989 | 1
A | 4-24-1989 | 5-1-1989 | 0
A | 6-14-1993 | 6-27-1993 | 0
A | 12-24-1999 | 1-2-2000 | 1
A | 1-19-2000 | 1-24-2000 | 0
B | 2-2-2000 | 2-7-2000 | 1
B | 5-27-2001 | 6-4-2001 | 0
You can select..., exists <select ... criteria>, that would return a boolean (always true or false) but if really want 1 or 0 just cast the result to integer: true=>1 and false=>0. See Demo
select ts1.user_id
, ts1.encounter_start
, ts1. encounter_stop
, (exists ( select null
from test_set ts2
where ts1.user_id = ts2.user_id
and ts2.encounter_start
between ts1.encounter_stop
and (ts1.encounter_stop + interval '30 days')::date
)::integer
) subsequent_encounter_within_30_days
from test_set ts1
order by user_id, encounter_start;
Difference: The above (and demo) disagree with your expected result:
B | 2-2-2000 | 2-7-2000| 1
subsequent_encounter (last column) should be 0. This entry starts and ends in Feb 2000, the other B entry starts In May 2001. Please explain how these are within 30 days (other than just a simple typo that is).
Caution: Do not use user as a column name. It is both a Postgres and SQL Standard reserved word. You can sometimes get away with it or double quote it. If you double quote it you MUST always do so. The big problem being it has a predefined meaning (run select user;) and if you forget to double quote is does not necessary produce an error or exception; it is much worse - wrong results.

How to build distribution table for number of digits after the dot in hive?

There is a string column converted from float(double) one in a hive table. I need a table that represents number of digits after dot with count rows for each number.
+-----+------+--+
| num | _c0 |
+-----+------+--+
| 2 | 300 |
| 3 | 400 |
| 4 | 248 |
| 5 | 117 |
| 6 | 43 |
| NULL| 999 |
+-----+------+--+
There is a function to obtain number of digits after dot in column foo
length(split(foo, '\\.')[1])
So, my failed attempt to obtain the above table was
select length(split(foo, '\\.')[1]) as num, count(num) from tbl_bar group by num;
The error message was
Error: Error while compiling statement: FAILED: SemanticException [Error 10004]: Line 1:77 Invalid table alias or column reference 'num': (possible column names are: foo, moo, hroo) (state=42000,code=10004)
What is the correct query to get distribution by number of digits after the dot in column foo?
Column-aliases can't be selected in the query at the same level. Use the actual calculation instead.
select length(split(foo, '\\.')[1]) as num, count(*)
from tbl_bar
group by length(split(foo, '\\.')[1]);

search a keyword in postgresql json field

I am currently using postgres 9.3.3
Following is how my table looks like -
Column | Type | Modifiers | Storage | Stats target | Description
--------------------+--------------------------+--------------------------------------------------------------------+----------+--------------+-------------
id | integer | not null default nextval('playerbase_palyerdata_id_seq'::regclass) | plain | |
date_joined | timestamp with time zone | not null | plain | |
belongs_to_camp_id | integer | not null | plain | |
belongs_to_coach_id | integer | not null | plain | |
json_kvps | character varying(2000) | not null | extended | |
One sample data is as follows -
id | date_joined | belongs_to_camp_id | belongs_to_coach_id | json_kvps
1 | 2014-03-07 18:10:45.824749+05:30 | 1 | 1 | {"alumnicode": "2003360009", "emailusername": "aaron#hotmail.com", "altemail": "", "salutation": "Mrs", "fname": "Aaron", "mname": "V", "lname": "Schwartz", "fullname": "Aaraon M Scwartz", "programmename": "MEP", "batchyearin": "2003"}
Now I want to search the entire table, and find a user with "emailusername":"aaron#hotmail.com"
As mentioned here -
http://www.postgresql.org/docs/current/static/functions-json.html
I try to write a query as follows -
SELECT * FROM playerbase_playerdata WHERE json_kvps->>'emailusername' = 'aaron#hotmail.com';
I was expecting a column as above, instead I got the following error -
ERROR: operator does not exist: character varying ->> unknown
LINE 1: ...ELECT * FROM memberbase_memberdata WHERE json_kvps->>'emailu...
^
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
Could someone please tell me, what am I missing?
Feature like this exists only from PostgreSQL release 9.3.
So, unfortunately, to make queries like this you need to update your PostgreSQL.
If you have 9.3, then you need use json column type.
Here you can see some example. It helps me, earlier:
http://clarkdave.net/2013/06/what-can-you-do-with-postgresql-and-json/
Have a nice day.
For PostgreSQL 9.3 or higher, one possible solution could be using a cast to json:
SELECT * FROM playerbase_playerdata WHERE json_kvps->>'emailusername' = 'aaron#hotmail.com';
SELECT * FROM playerbase_playerdata WHERE CAST(json_kvps AS JSON)->>'emailusername' = 'aaron#hotmail.com';
In case of django models you can use JsonField.
https://pypi.python.org/pypi/jsonfield.
It works fine, but if you'll use PostgreSQL version less than 9.2, it'll create character column.
select [Required Fields] from [Table Name] WHERE [Column Name]::text = '{[Key]}' ::text

How to get numbers arranged right to left in sql server SELECT statements

When performing SELECT statements including number columns (prices, for example), the result always is left to right ordered, which reduces the readability. Therefore I'm searching a method to format the output of number columns right to left.
I already tried to use something like
SELECT ... SPACE(15-LEN(A.Nummer))+A.Nummer ...
FROM Artikel AS A ...
which gives close results, but depending on font not really. An alternative would be to replace 'SPACE()' with 'REPLICATE('_',...)', but I don't really like the underscores in output.
Beside that this formula will crash on numbers with more digits than 15, therefore I searched for a way finding the maximum length of entries to make it more save like
SELECT ... SPACE(MAX(A.Nummer)-LEN(A.Nummer))+A.Nummer ...
FROM Artikel AS A ...
but this does not work due to the aggregate character of the MAX-function.
So, what's the best way to achieve the right-justified order for the number-columns?
Thanks,
Rainer
To get you problem with the list box solved have a look at this link: http://www.lebans.com/List_Combo.htm
I strongly believe that this type of adjustment should be made in the UI layer and not mixed in with data retrieval.
But to answer your original question i have created a SQL Fiddle:
MS SQL Server 2008 Schema Setup:
CREATE TABLE dbo.some_numbers(n INT);
Create some example data:
INSERT INTO dbo.some_numbers
SELECT CHECKSUM(NEWID())
FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))X(x);
The following query is using the OVER() clause to specify that the MAX() is to be applied over all rows. The > and < that the result is wrapped in is just for illustration purposes and not required for the solution.
Query 1:
SELECT '>'+
SPACE(MAX(LEN(CAST(n AS VARCHAR(MAX))))OVER()-LEN(CAST(n AS VARCHAR(MAX))))+
CAST(n AS VARCHAR(MAX))+
'<'
FROM dbo.some_numbers SN;
Results:
| COLUMN_0 |
|---------------|
| >-1486993739< |
| > 1620287540< |
| >-1451542215< |
| >-1257364471< |
| > -819471559< |
| >-1364318127< |
| >-1190313739< |
| > 1682890896< |
| >-1050938840< |
| > 484064148< |
This query does a straight case to show the difference:
Query 2:
SELECT '>'+CAST(n AS VARCHAR(MAX))+'<'
FROM dbo.some_numbers SN;
Results:
| COLUMN_0 |
|---------------|
| >-1486993739< |
| >1620287540< |
| >-1451542215< |
| >-1257364471< |
| >-819471559< |
| >-1364318127< |
| >-1190313739< |
| >1682890896< |
| >-1050938840< |
| >484064148< |
With this query you still need to change the display font to a monospaced font like COURIER NEW. Otherwise, as you have noticed, the result is still misaligned.