SQL INSERT INTO with subquery and value - sql

Is there a way I can use a combination of hard values and a subquery to insert into a table with one command?
For example:
INSERT INTO suppliers (supplier_id, supplier_name, supplier_type)
SELECT account_no, name
FROM customers
WHERE city = 'San Diego';
I need supplier_type to be 3. So can I do the following for the second line?
SELECT account_no, name, supplier_type = 3
supplier_type is not in the customers table

Just add it with your SELECT fields.
INSERT INTO suppliers (supplier_id, supplier_name, supplier_type)
SELECT account_no, name, 3 AS supplier_type
FROM customers
WHERE city = 'San Diego';

Even simpler, just fill in the field with the value, dont even need an AS:
INSERT INTO suppliers (supplier_id, supplier_name, supplier_type)
SELECT account_no, name, 3
FROM customers
WHERE city = 'San Diego';

Related

Oracle. apply Conditional ordering. If >=2 rows have duplicate data, those rows must follow a seperate condition to those that don't have duplicates

Select custno, custname, location
From customer
Order by
The order of the results have to fit the following criteria:
custno, custnames and location in ascending location sequence. If 2 or more rows have the same location, list only those rows in ascending custname sequence.
I don't even know where to begin with the 2nd part of the question.
I found questions somewhat similar to this and it was advised to use case with when, but I've never used that before, and not sure what to begin. Here's where I'm at so far
Select custno, custname, location
From customer
Order by
Case
when count(location) >= 2
then custname asc
else location asc
end
This is the pic of the results they provided.
And the statements that was provided.
create table GRADE (
gradeID varchar2(2),
description varchar2(20),
Primary Key (gradeID) );
create table TYPE (
TypeCode number,
Title varchar2(20),
gradeID varchar2(2),
category varchar2(1),
Primary Key (TypeCode),
Foreign Key (gradeID) references GRADE );
create table customer(
custno number,
custname varchar2(20),
typecode number,
sales number(7,2),
location varchar2(20),
Primary Key (custno),
Foreign Key (typecode) references TYPE );
Insert into grade (gradeID,description) values ('WC','Women and
Children');
Insert into grade (gradeID,description) values ('M','Men');
Insert into TYPE (TypeCode,Title,gradeID,category) values (1,'Under
20','WC','X');
Insert into TYPE (TypeCode,Title,gradeID,category) values (2,'Under
20','M','Z');
Insert into TYPE (TypeCode,Title,gradeID,category) values (3,'20
plus','WC','Z');
Insert into TYPE (TypeCode,Title,gradeID,category) values (4,'20
plus','M','X');
Insert into TYPE (TypeCode,Title,gradeID,category) values
(5,'Special','M','S');
Insert into customer (custno, custname, TypeCode,sales,location) values
(21,'Wendy',1,300,'Haw');
Insert into customer (custno, custname, TypeCode,sales,location) values
(24,'Sue',3,700,'Haw');
Insert into customer (custno, custname, TypeCode,sales,location) values
(27,'Nick',2,NULL,'Kew');
Insert into customer (custno, custname, TypeCode,sales,location) values
(22,'Dave',4,95,'Richmond');
Insert into customer (custno, custname, TypeCode,sales,location) values
(25,'Jenny',1,525,'Haw');
Insert into customer (custno, custname, TypeCode,sales,location) values
(29,'Bob',4,15,'Kew');
Insert into customer (custno, custname, TypeCode,sales,location) values
(23,'Helen',3,200,'Haw');
Insert into customer (custno, custname, TypeCode,sales,location) values
(28,'Linda',1,25,'Kew');
Insert into customer (custno, custname, TypeCode,sales,location) values
(26,'Xena',3,Null, 'Richmond');
Start with a query that returns nr of identical rows, then select only rows with nr > 1:
select ...
from customer c,
(
Select count(*) nr, location
From customer
Group by location
) n
where n.nr > 1
and c.l = n.l
This isn't a complete query, but you get the idea. It is hard for me to get this exactly right without having your table.

Returning identity of INSERT for new INSERT with data outside of RETURNING clause

I'm using PostgreSQL 12.3.
Similar to the many questions that have been asked about this, like this one, but I need to use data from another table that isn't present in the RETURNING clause.
For a contrived example, consider three tables: customers, products, and sales, and a scenario where a customer needs to be created at the point of sale, and the sales table needs to be updated with both the users and products ids.
CREATE TABLE public.customers (
id SERIAL PRIMARY KEY,
first_name TEXT NOT NULL,
last_name TEXT NOT NULL
)
CREATE TABLE public.products (
id SERIAL PRIMARY KEY,
product TEXT NOT NULL
)
CREATE TABLE public.sales (
id SERIAL PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers(id),
product_id INTEGER NOT NULL REFERENCES products(id)
)
INSERT INTO customers (first_name, last_name) VALUES ('Bob', 'Smith');
INSERT INTO customers (first_name, last_name) VALUES ('Jane', 'Doe');
INSERT INTO products (product) VALUES ('widget 1');
INSERT INTO products (product) VALUES ('widget 2');
INSERT INTO products (product) VALUES ('widget 3');
INSERT INTO sales (customer_id, product_id) VALUES (1, 1);
INSERT INTO sales (customer_id, product_id) VALUES (2, 1);
INSERT INTO sales (customer_id, product_id) VALUES (2, 2);
If I just need the customer id, the following wouldn't be a problem:
WITH new_customer_and_new_sale AS (
INSERT INTO customers (first_name, last_name) VALUES ('John', 'Doe') RETURNING id
)
INSERT INTO sales (customer_id)
SELECT id FROM new_user_and_new_sale
Since sales has constraints not found in the returning clause, the above obviously won't work. I've tried joining tables to pull in the additional data, but haven't been able to get it to work.
Please overlook any minor issues you may have with the structure of the tables, as the data I'm working with has hundreds of columns and many foreign keys. I've tried to condense the problem into its simplest form, at the risk of seeming contrived.
Your example fails because you're not providing the value for product_id, which is required.
You can directly specify one like this:
WITH inserted_customer AS (
INSERT INTO customers (first_name, last_name) VALUES ('acacaca', 'Doe') RETURNING id
)
INSERT INTO sales (customer_id, product_id)
SELECT inserted_customer.id, 2 FROM inserted_customer;
If you want to get the product ID from an existing product you can do it with a subquery (or a CTE if you're doing more complicated stuff).
WITH inserted_customer AS (
INSERT INTO customers (first_name, last_name) VALUES ('acacaca', 'Doe') RETURNING id
)
INSERT INTO sales (customer_id, product_id)
SELECT inserted_customer.id, (SELECT id FROM products ORDER BY id DESC LIMIT 1) FROM inserted_customer;
If you want to insert the customer and the product on the fly, you can do two CTEs:
WITH inserted_customer AS (
INSERT INTO customers (first_name, last_name) VALUES ('acacaca', 'Doe') RETURNING id
),
inserted_product AS (
INSERT INTO products (product) VALUES ('my product') RETURNING id
)
INSERT INTO sales (customer_id, product_id)
SELECT inserted_customer.id, inserted_product.id
FROM inserted_customer, inserted_product;
Hope this helps!

How to insert new row without duplicating existing data

I want to insert rows in my table like so:
my columns are student,subject,class,teacher,level. Primary key is (student,subject). The table contains all the students, but the Math subject is missing for some of them, so I want to add it without duplicating the ones that already have it.
I've tried this but it gives me unique constraint violated:
insert into table (student,subject,class,teacher,level)
select a.student, 'math', null, null, null
from table a
where a.student in (select distinct student from table where subject not in 'math')
and (a.student,a.subject) not in (select student,subject from table);
I think you basically need select distinct:
insert into table (student, subject)
select distinct a.student, 'math'
from table a
where not exists (select 1
from table a2
where a2.student = a.student and
a2.subject = 'math'
);
One approach would be to use minus:
insert into course_students (student, subject)
select student, 'Math' from course_students
minus
select student, subject from course_students;
This would would need extending a little if you wanted to include other columns in the insert:
insert into course_students (student, subject, class, teacher, course_level)
select student, subject, '101', 'Naomi', 1
from ( select student, 'Math' as subject from course_students
minus
select student, subject from course_students );

How to hide distinct column in sql selection

I am doing a query in sql to find rows with distinct value of name as below:
select distinct name, age, sex from person
it works but I don't want to show the name column in the result set. Is there a way to hide this column?
EDIT1
the reason I put distinct name there is to avoid multiple rows with the same name returned. My table has person with the same name but different age and sex. So I want to make the result distinct in name but don't show the name.
You could try something like this.
select age, sex from (
select distinct name, age, sex from person);
I'm presuming you might have people with the same age and sex but a different name.
Otherwise just remove the name
Here is my solution (sql server 2016):
create table person (age varchar(20), [name] varchar(20), gender varchar(20))
go
insert into person values ('20', 'joe', 'm')
insert into person values ('19', 'tom', 'm')
insert into person values ('25', 'sally', 'f')
insert into person values ('28', 'Tammy', 'f')
go
select age, gender from (select distinct name, age, gender from person) t
You have to use your query as a sub query here.
From your query again select age and sex alone.
select age, sex from (select distinct name, age, sex from person) As x

Counting the instances of customers

Say that I have a table with one column named CustomerId.
The example of the instance of this table is :
CustomerId
14
12
11
204
14
204
I want to write a query that counts the number of occurences of customer IDs.
At the end, I would like to have a result like this :
CustomerId NumberOfOccurences
14 2
12 1
11 1
204 2
14 1
I cannot think of a way to do this.
This is the most basic example of GROUP BY
SELECT CustomerId, count(*) as NumberOfOccurences
FROM tablex GROUP BY CustomerId;
Practice exercise #3 on this page explains how to do this.
CREATE TABLE customers
( customer_id number(10) not null,
customer_name varchar2(50) not null,
city varchar2(50),
CONSTRAINT customers_pk PRIMARY KEY (customer_id)
);
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7001, 'Microsoft', 'New York');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7002, 'IBM', 'Chicago');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7003, 'Red Hat', 'Detroit');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7004, 'Red Hat', 'New York');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7005, 'Red Hat', 'San Francisco');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7006, 'NVIDIA', 'New York');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7007, 'NVIDIA', 'LA');
INSERT INTO customers (customer_id, customer_name, city)
VALUES (7008, 'NVIDIA', 'LA');
Solution:
The following SQL statement would return the number of distinct cities for each customer_name in the customers table:
SELECT customer_name, COUNT(DISTINCT city) as "Distinct Cities"
FROM customers
GROUP BY customer_name;
It would return the following result set:
CUSTOMER_NAME Distinct Cities
IBM 1
Microsoft 1
NVIDIA 2
Red Hat 3