Column does not exits in Postgresql - database

I created a table:
CREATE TABLE LuxRoom
(
roomID INT NOT NULL PRIMARY KEY CONSTRAINT roomID_ref_room REFERENCES Room(roomID),
peopleNumber INT NOT NULL,
additionalService TEXT
)
But when I do insert like this:
INSERT INTO LuxRoom(roomID, peopleNumber, additionalService) VALUES(1, 2, "Extra food, a cab");
I get this error:
ERROR: column "Extra food, a cab" does not exist
What is the problem?

Single quotes delimit a string constant or a date/time constant.
Double quotes delimit identifiers for e.g. table names or column
names. This is generally only necessary when your identifier doesn't
fit the rules for simple identifiers.
replace double quotes with single quote
INSERT INTO LuxRoom (roomID, peopleNumber, additionalService)
VALUES (1, 2, 'Extra food, a cab');

PostgreSQL is "picky" in terms of SQL syntax and makes a difference between ' and ". " indicates, that it's an object, ' it's a string. So your query should look like
INSERT INTO LuxRoom(roomID, peopleNumber, additionalService)
VALUES(1, 2, 'Extra food, a cab');
This is different to e.g. behaviour on MySQL, but the standard way.

Related

Snowflake: Trouble getting numbers to return from a PIVOT function

I am moving a query from SQL Server to Snowflake. Part of the query creates a pivot table. The pivot table part works fine (I have run it in isolation, and it pulls numbers I expect).
However, the following parts of the query rely on the pivot table- and those parts fail. Some of the fields return as a string-type. I believe that the problem is Snowflake is having issues converting string data to numeric data. I have tried CAST, TRY_TO_DOUBLE/NUMBER, but these just pull up 0.
I will put the code down below, and I appreciate any insight as to what I can do!
CREATE OR REPLACE TEMP TABLE ATTR_PIVOT_MONTHLY_RATES AS (
SELECT
Market,
Coverage_Mo,
ZEROIFNULL(TRY_TO_DOUBLE('Starting Membership')) AS Starting_Membership,
ZEROIFNULL(TRY_TO_DOUBLE('Member Adds')) AS Member_Adds,
ZEROIFNULL(TRY_TO_DOUBLE('Member Attrition')) AS Member_Attrition,
((ZEROIFNULL(CAST('Starting Membership' AS FLOAT))
+ ZEROIFNULL(CAST('Member Adds' AS FLOAT))
+ ZEROIFNULL(CAST('Member Attrition' AS FLOAT)))-ZEROIFNULL(CAST('Starting Membership' AS FLOAT)))
/ZEROIFNULL(CAST('Starting Membership' AS FLOAT)) AS "% Change"
FROM
(SELECT * FROM ATTR_PIVOT
WHERE 'Starting Membership' IS NOT NULL) PT)
I realize this is a VERY big question with a lot of moving parts... So my main question is: How can I successfully change the data type to numeric value, so that hopefully the formulas work in the second half of the query?
Thank you so much for reading through it all!
EDITED FOR SHORTENING THE QUERY WITH UNNEEDED SYNTAX
CAST(), TRY_TO_DOUBLE(), TRY_TO_NUMBER(). I have also put the fields (Starting Membership, Member Adds) in single and double quotation marks.
Unless you are quoting your field names in this post just to highlight them for some reason, the way you've written this query would indicate that you are trying to cast a string value to a number.
For example:
ZEROIFNULL(TRY_TO_DOUBLE('Starting Membership'))
This is simply trying to cast a string literal value of Starting Membership to a double. This will always be NULL. And then your ZEROIFNULL() function is turning your NULL into a 0 (zero).
Without seeing the rest of your query that defines the column names, I can't provide you with a correction, but try using field names, not quoted string values, in your query and see if that gives you what you need.
You first mistake is all your single quoted columns names are being treated as strings/text/char
example your inner select:
with ATTR_PIVOT(id, studentname) as (
select * from values
(1, 'student_a'),
(1, 'student_b'),
(1, 'student_c'),
(2, 'student_z'),
(2, 'student_a')
)
SELECT *
FROM ATTR_PIVOT
WHERE 'Starting Membership' IS NOT NULL
there is no "starting membership" column and we get all the rows..
ID
STUDENTNAME
1
student_a
1
student_b
1
student_c
2
student_z
2
student_a
So you need to change 'Starting Membership' -> "Starting Membership" etc,etc,etc
As Mike mentioned, the 0 results is because the TRY_TO_DOUBLE always fails, and thus the null is always turned to zero.
now, with real "string" values, in real named columns:
with ATTR_PIVOT(Market, Coverage_Mo, "Starting Membership", "Member Adds", "Member Attrition") as (
select * from values
(1, 10 ,'student_a', '23', '150' )
)
SELECT
Market,
Coverage_Mo,
ZEROIFNULL(TRY_TO_DOUBLE("Starting Membership")) AS Starting_Membership,
ZEROIFNULL(TRY_TO_DOUBLE("Member Adds")) AS Member_Adds,
ZEROIFNULL(TRY_TO_DOUBLE("Member Attrition")) AS Member_Attrition
FROM ATTR_PIVOT
WHERE "Starting Membership" IS NOT NULL
we get what we would expect:
MARKET
COVERAGE_MO
STARTING_MEMBERSHIP
MEMBER_ADDS
MEMBER_ATTRITION
1
10
0
23
150

Snowflake float type column out of range error

I got Numeric value out of range error when trying to insert two values into a Float type column.
create or replace table num_test(float_num float); -- create table and column
INSERT INTO num_test (float_num)VALUES (1.0528618730874378E10), (-3.694822225952521E-13);
The error i got shows: "Numeric value '10528618730.874378' is out of range."
But when i try to insert these two values separately, it work fine.
INSERT INTO num_test (float_num)VALUES (1.0528618730874378E10); -- ok
INSERT INTO num_test (float_num)VALUES (-3.694822225952521E-13); -- ok
I couldn't see any out of range issues on the snowflake document for the values I tried to insert.
If I had to guess what the problem was, it would be that "the guess of the "type" based on the first value in the VALUES is smaller than the type of the second value".
So if we just try and select those values with zero target problems:
select column1, system$typeof(column1)
from VALUES
(1.0528618730874378E10),
(-3.694822225952521E-13);
triggers.
Numeric value '10528618730.874378' is out of range
One at a time we get:
COLUMN1
SYSTEM$TYPEOF(COLUMN1)
-0.0000000000003695
NUMBER(29,28)[SB16]
COLUMN1
SYSTEM$TYPEOF(COLUMN1)
10,528,618,730.874378
NUMBER(17,6)[SB8]
So sure enough the two random "numbers" are cast to two different types, and these are deemed "too different". Thus my guess was correct.
What to do about this:
So we inline cast them:
select column1, system$typeof(column1)
from VALUES
(1.0528618730874378E10::double),
(-3.694822225952521E-13::double)
;
we get
COLUMN1
SYSTEM$TYPEOF(COLUMN1)
10,528,618,730.8744
FLOAT[DOUBLE]
-0.0000000000003695
FLOAT[DOUBLE]
so the values are safe if we first tell the DB what they are, and avoid the auto guessing code.
thus in your context:
INSERT INTO num_test (float_num)VALUES
(1.0528618730874378E10::double),
(-3.694822225952521E-13::double)
;
number of rows inserted
2

Postgres String Array Comparison

I have an array of the form :
myArray = ["1234-56", "1234-567"]
My table has a column which is constructed exactly like the array and consists of a string array, we call the column : myColumn.
I want to output the rows where , one or more values of the arrays match.
My current attempt was the following :
SELECT *
FROM myTable
WHERE myColumn && myArray;
But this ends with the following error message:
ERROR: Column "56" does not exist.
A string in double quotes is an “identifier” in SQL, that is the name of a table, column, function or other object.
So when you write
SELECT * FROM mytable
WHERE mycolumn && ARRAY["56","95"];
PostgreSQL will identify "56" as a column name (it couldn't be a table in that context), and it complaint that table mytable has no column called 56.
The solution is to mark 56 as a string literal, that is, surround it with single quotes:
SELECT * FROM mytable
WHERE mycolumn && ARRAY['56','95'];

SQL assignment: Using Variables and using IF statements

Okay, So here is the first question on the assignment. I just don't know where to start with the problem. If anyone could just help me get started I'd be able to figure it out probably. Thanks
Set two variable values as follows:
#minEnrollment = 10
#maxEnrollment = 20
Determine the number of courses with enrollments between the values assigned to #minEnrollment and #maxEnrollment. If there are courses with enrollments between these two values, display a message in the form
There is/are __class(es) with enrollments between __ and __..
If there are no classes within the defined range, display a message in the form
“
There are no classes with an enrollment between __ and __ students.”
.....
And here is the database to use:
CREATE TABLE Faculty
(Faculty_ID INT PRIMARY KEY IDENTITY,
LastName VARCHAR (20) NOT NULL,
FirstName VARCHAR (20) NOT NULL,
Department VARCHAR (10) SPARSE NULL,
Campus VARCHAR (10) SPARSE NULL);
INSERT INTO Faculty VALUES ('Brown', 'Joe', 'Business', 'Kent');
INSERT INTO Faculty VALUES ('Smith', 'John', 'Economics', 'Kent');
INSERT INTO Faculty VALUES ('Jones', 'Sally', 'English', 'South');
INSERT INTO Faculty VALUES ('Black', 'Bill', 'Economics', 'Kent');
INSERT INTO Faculty VALUES ('Green', 'Gene', 'Business', 'South');
CREATE TABLE Course
(Course_ID INT PRIMARY KEY IDENTITY,
Ref_Number CHAR (5) CHECK (Ref_Number LIKE '[0-9][0-9][0-9][0-9][0-9]'),
Faculty_ID INT NOT NULL REFERENCES Faculty (Faculty_ID),
Term CHAR (1) CHECK (Term LIKE '[A-C]'),
Enrollment INT NULL DEFAULT 0 CHECK (Enrollment < 40))
INSERT INTO Course VALUES ('12345', 3, 'A', 24);
INSERT INTO Course VALUES ('54321', 3, 'B', 18);
INSERT INTO Course VALUES ('13524', 1, 'B', 7);
INSERT INTO Course VALUES ('24653', 1, 'C', 29);
INSERT INTO Course VALUES ('98765', 5, 'A', 35);
INSERT INTO Course VALUES ('14862', 2, 'B', 14);
INSERT INTO Course VALUES ('96032', 1, 'C', 8);
INSERT INTO Course VALUES ('81256', 5, 'A', 5);
INSERT INTO Course VALUES ('64321', 2, 'C', 23);
INSERT INTO Course VALUES ('90908', 3, 'A', 38);
Your request is how to get started, so I'm going to focus on that instead of any specific code.
Start by getting the results that are being asked for, then move on to formatting them as requested.
First, work with the Course table and your existing variables, #minEnrollment = 10 and #maxEnrollment = 20, to get the list that meets the enrollment requirements. Hint: WHERE and BETWEEN. (The Faculty table you have listed doesn't factor into this at all.) After you're sure you have the right results in that list, use the COUNT function to get the number you need for your answer, and assign that value to a new variable.
Now, to the output. IF your COUNT variable is >0, CONCATenate a string together using your variables to fill in the values in the sentence you're supposed to write. ELSE, use the variables to fill in the other sentence.
Part of the problem is, you've actually got 3 or so questions in your post. So instead of trying to post a full answer, I'm instead going to try to get you started with each of the subquestions.
Subquestion #1 - How to assign variables.
You'll need to do some googling on 'how to declare a variable in SQL' and 'how to set a variable in SQL'. This one won't be too hard.
Subquestion #2 - How to use variables in a query
Again, you'll need to google how to do this - something like 'How to use a variable in a SQL query'. You'll find this one is pretty simple as well.
Subquestion #3 - How to use IF in SQL Server.
Not to beat a dead horse, but you'll need to google this. However, one thing I would like to note: I'd test this one first. Ultimately, you're going to want something that looks like this:
IF 1 = 1 -- note, this is NOT the correct syntax (on purpose.)
STUFF
ELSE
OTHERSTUFF
And then switch it to:
IF 1 = 2 -- note, this is NOT the correct syntax (on purpose.)
STUFF
ELSE
OTHERSTUFF
... to verify the 'STUFF' happens when the case is true, and that it otherwise does the 'OTHERSTUFF'. Only after you've gotten it down, should you try to integrate it in with your query (otherwise, you'll get frustrated not knowing what's going on, and it'll be tougher to test.)
One step at a time. Let me give you some help:
Set two variable values as follows: #minEnrollment = 10 #maxEnrollment
= 20
Translated to SQL, this would look like:
Declare #minEnrollment integer = 10
Declare #maxEnrollment integer =15
Declare #CourseCount integer = 0
Determine the number of courses with enrollments between the values
assigned to #minEnrollment and #maxEnrollment.
Now you have to query your tables to determine the count:
SET #CourseCount = (SELECT Count(Course_ID) from Courses where Enrollment > #minEnrollment
This doesn't answer your questions exactly (ON PURPOSE). Hopefully you can spot the mistakes and fix them yourself. The other answers gave you some helpful hints as well.

Bulk insert in SQL Server with a regional separator

I want to make bulk insert of data where decimal separator is a comma as in regional settings.
The data are the following:
RegionName Value_1 Value_2 Value_3
Region 1 27,48 66,41 32,82
Region 2 38,93 45,80 61,83
Region 3 38,17 58,02 35,11
Region 4 34,35 16,03 29,01
Region 5 67,94 58,02 17,56
I make the bulk insert using this script:
create table RegVaues (
RegionName varchar(30)
,Value_1 float
,Value_2 float
,Value_3 float
)
go
bulk insert RegVaues
from N'A:\TestValues.txt'
with
(
DATAFILETYPE = 'widechar'
,fieldterminator = '\t'
,rowterminator = '\n'
,firstrow = 2
,keepnulls
)
go
After fulfilling a scrip I receive an error:
sg 4864, Level 16, State 1, Line 2 Bulk load data conversion error
(type mismatch or invalid character for the specified codepage) for
row 2, column 2 (Value_1).
When I try the same with a dot as a separator - all works. I have tried to insert the data with different types (float, decimal, numeric). In my SSMS in Tools->Options->International Settings the Language is set to "Same as in Microsoft Windows". The database collation is Ukrainian_CI_AS. But still the data with a comma separator couldn't be inserted. What I'm doing wrong?
Well the error is self explanatory, values with commas in them are not float values and when you are to insert values like 27,48 , 66,41 into a float column, it tries to convert them values to float and it fails hence the error message.
A simple solution would be to insert the data into a holding/staging table first with column data type character (VarChar) , then replace the commas with a decimal point and then use them values to insert into your final destination table.
Also mind you float is an approximate data type and should only be used for approximate values like (mass of earth and distance between planets etc) for exact values use DECIMAL or NUMERIC data types.

Resources