Using PostgreSQL with clause show count from two tables - sql

I have four tables advertisement,sales_enquiry,sales_estimate and sales_leadsource. Database used is PostgreSQL. I want to get the count of sales_enquiry and count of sales_estimate for an advertisement, advertisement and sales_enquiry has the id of sales_leadsource as foreign key, sales_estimate table has the id of sales_enquiry as foreign key. I have tried using the following query but result is not getting correctly.
Table schema is
TABLE sales_leadsource
(
leadsource_id serial NOT NULL,
leadsource character varying(250),
CONSTRAINT sales_leadsource_pkey PRIMARY KEY (leadsource_id)
)
TABLE advertisement
(
id serial NOT NULL,
ad_source_name character varying(200),
amount numeric(18,2),
duration character varying(50),
leadsource_id integer,
CONSTRAINT advertisement_pkey PRIMARY KEY (id),
CONSTRAINT advertisement_leadsource_id_fkey FOREIGN KEY (leadsource_id)
REFERENCES sales_leadsource (leadsource_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT
)
TABLE sales_enquiry
(
enquiry_id serial NOT NULL,
leadsource_id integer,
customer_name character varying(200),
advertisement_id integer,
CONSTRAINT sales_enquiry_pkey PRIMARY KEY (enquiry_id),
CONSTRAINT sales_enquiry_advertisement_id_fkey FOREIGN KEY (advertisement_id)
REFERENCES advertisement (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT
)
TABLE sales_estimate
(
ref_no integer NOT NULL,
enquiry_id integer,
property_id integer,
sqft_amount numeric,
CONSTRAINT sales_estimate_pkey PRIMARY KEY (ref_no),
CONSTRAINT sales_estimate_enquiry_id_fkey FOREIGN KEY (enquiry_id)
REFERENCES sales_enquiry (enquiry_id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE RESTRICT
)
Query is as follows
with campaign as(
select se.leadsource_id,se.advertisement_id,count(*) as leads_count from sales_enquiry se group by se.advertisement_id,se.leadsource_id
),
converted as(
select se.leadsource_id,se.advertisement_id,count(*) as converted_count from sales_enquiry se
left join sales_estimate sm on se.enquiry_id=sm.enquiry_id
where sm.status_id=1 and sm.application_status=1 or sm.application_status=2
group by se.advertisement_id,se.leadsource_id
)
select a.id,
coalesce(a.ad_source_name,'None'),
a.amount,
a.duration,
c.leads_count,
c.leadsource_id,
sl.leadsource,
cv.converted_count
From advertisement a
right join campaign c on a.id=c.advertisement_id
left join converted cv on c.advertisement_id=cv.advertisement_id
left join advertisement_status ads on a.status_id=ads.status_id
left join sales_leadsource sl on c.leadsource_id=sl.leadsource_id;
Please help. Thanks in advance.

Related

is it possible in SQL to call two difrent table with difrent data at the same time

so basicly what i need is to get two tables at the same time and then use a condition that reside in the first table and i want to apply it to the second one
if it not possible do i need to call SELECT Twice ?
is this code right ?
to determine the average rating of all movies released in 2012
SELECT AVG(rating),year FROM ratings , movies
WHERE year = 2012;
//these are the tables that i have
CREATE TABLE movies (
id INTEGER,
title TEXT NOT NULL,
year NUMERIC,
PRIMARY KEY(id)
);
CREATE TABLE stars (
movie_id INTEGER NOT NULL,
person_id INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id),
FOREIGN KEY(person_id) REFERENCES people(id)
);
CREATE TABLE directors (
movie_id INTEGER NOT NULL,
person_id INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id),
FOREIGN KEY(person_id) REFERENCES people(id)
);
CREATE TABLE ratings (
movie_id INTEGER NOT NULL,
rating REAL NOT NULL,
votes INTEGER NOT NULL,
FOREIGN KEY(movie_id) REFERENCES movies(id)
);
CREATE TABLE people (
id INTEGER,
name TEXT NOT NULL,
birth NUMERIC,
PRIMARY KEY(id)
);
I think you want a JOIN and an aggregate function:
SELECT AVG(r.rating) avg_rating_2012
FROM ratings r
INNER JOIN movies m on m.id = r.movie_id
WHERE m.year = 2012;
If you want this for all years at once, then use GROUP BY:
SELECT m.year, AVG(r.rating) avg_rating
FROM ratings r
INNER JOIN movies m on m.id = r.movie_id
GROUP BY m.year;

Is there a way to implement count in left join

I'm setting up a chat-Group application using a simple database. I want to know if there is a way for me to see the people that liked/disliked a certain post, which can have a picture or a video attached to it. The important information I want to know is the post ID, message of the post, date of the post, url of the picture I want to post, url of the video, and the id of the user posting said post. I'm using left joins to see all this information, but I'm missing if the posts have likes or dislikes.
I already tried using the aggregate count to see each like and dislike of the posts, but I don't know how to mix this query with the previous information.
This is my query to see the information listed above:
select P.post_ID, P.post_msg, P.post_date, F.photo_url,V.video_url, P.user_ID
from ((Post as P left join Photo as F on P.post_ID = F.post_ID ) left join Video as V
on P.post_ID = V.post_ID)
where P.chat_ID = 1
Here is the output of the Query:
Here is an example of the output I want:
The query above displays everything I'm looking for except each like and dislike of each post. Is there anyway to see this information mixed with what I want?
Here is the structure of the DataBase:
create table Login(login_ID serial primary key, login_Date DATE NOT NULL DEFAULT CURRENT_DATE, user_name varchar(20) NOT NULL);
create table Users(user_ID serial primary key, user_name varchar(20) NOT NULL, user_password varchar(20) NOT NULL);
create table Contact_List(contactlist_ID serial primary key, user_name varchar(20) NOT NULL,user_ID integer references Users(user_ID) on delete cascade);
create table Person(person_ID serial primary key, person_name varchar(20) NOT NULL, person_lastname varchar(30) NOT NULL, person_phone varchar(12), person_email varchar(50) NOT NULL, user_ID INTEGER references Users(user_ID) on delete cascade);
create table Admin(admin_ID serial primary key, user_ID INTEGER references Users(user_ID) on delete cascade);
create table Chat_Group(chat_ID serial primary key, chat_name varchar(50) NOT NULL, admin_Id INTEGER references Admin(admin_ID) on delete cascade);
create table Group_List(user_ID INTEGER references Users(user_ID) on delete cascade, chat_ID integer references Chatgroup(chat_id) on delete cascade, primary key(user_id, chat_id));
create table Post(post_ID serial primary key, post_msg varchar(280), post_date DATE NOT NULL DEFAULT CURRENT_DATE, user_ID INTEGER references Users(user_ID) on delete cascade, chat_ID INTEGER references Chatgroup(chat_ID) on delete cascade);
create table Video(video_ID serial primary key, video_url varchar(280) NOT NULL, post_ID INTEGER references Post(post_ID) on delete cascade);
create table Photo(photo_ID serial primary key, photo_url varchar(280) NOT NULL, post_ID INTEGER references Post(post_ID) on delete cascade);
create table Reply(reply_ID serial primary key, reply_msg varchar(280) NOT NULL, reply_Date DATE NOT NULL DEFAULT CURRENT_DATE, post_ID INTEGER references Post(post_ID) on delete cascade, user_ID INTEGER references Users(user_ID) on delete cascade);
create table HashTag(hashtag_ID serial primary key, hashtag_msg varchar(200) NOT NULL,post_ID INTEGER references Post(post_ID) on delete cascade NOT NULL, user_ID INTEGER references Users(user_ID) on delete cascade);
create table Reaction(reaction_ID serial primary key,reaction_date DATE NOT NULL DEFAULT CURRENT_DATE, reaction_like BOOLEAN, reaction_dislike BOOLEAN, post_ID INTEGER references Post(post_ID) on delete cascade, user_ID INTEGER references users(user_ID) on delete cascade);
create table React_to(reaction_ID INTEGER references Reaction(reaction_ID) on delete cascade, reply_ID INTEGER references Reply(reply_ID) on delete cascade, primary key(reaction_ID,reply_ID));
Excuse me for my bad english, english is not my main language.
One way of doing this would use correlated subquery.
SELECT p.post_id,
p.post_msg,
p.post_date,
f.photo_url,
v.video_url,
p.user_id,
(SELECT count(*)
FROM reaction r
WHERE r.post_id = p.post_id
AND r.reaction_like) likes,
(SELECT count(*)
FROM reaction r
WHERE r.post_id = p.post_id
AND r.reaction_dislike) dislikes
FROM post p
LEFT JOIN photo f
ON p.post_id = f.post_id
LEFT JOIN video v
ON p.post_id = v.post_id
WHERE p.chat_id = 1;
However I wonder if a reaction can be both a like and a dislike at once. At least your data model allowes such a thing...
I don't like the idea of going to the reactionss table twice. One way to avoid this is to use a lateral join:
select P.post_ID, P.post_msg, P.post_date, F.photo_url, V.video_url, P.user_ID,
r.num_likes, r.num_dislikes
from Post P left join
Photo F
on P.post_ID = F.post_ID left join
Video V
on P.post_ID = V.post_ID left join lateral
(select sum(r.reaction_like) as num_likes,
sum(r.reaction_dislike) as num_dislikes
from reactions r
where r.post_id = p.post_id
) r
on 1=1
where P.chat_ID = 1

Select a product that is on all interventions

Hello my question is simple for some of yours ^^
I've a table product, reference, and intervention. When there is an intervention the table reference make the link between products that we need for the interventions and the intervention.
I would like to know how to do to search products that have made part of all interventions.
This are my tables :
--TABLE products
create table products (
reference char(5) not null check ( reference like 'DT___'),
designation char(50) not null,
price numeric (9,2) not null,
primary key(reference) );
-- TABLE interventions
create table interventions (
nointerv integer not null ,
dateinterv date not null,
nameresponsable char(30) not null,
nameinterv char(30) not null,
time float not null check ( temps !=0 AND temps between 0 and 8),
nocustomers integer not null ,
nofact integer not null ,
primary key( nointerv),
foreign key( noclient) references customers,
foreign key (nofacture) references facts
);
-- TABLE replacements
create table replacements (
reference char(5) not null check ( reference like 'DT%'),
nointerv integer not null,
qtereplaced smallint,
primary key ( reference, nointerv ),
foreign key (reference) references products,
foreign key(nointerv) references interventions(nointerv)
);
--EDIT :
This is a select from my replacement table
We can see in this picture that the product DT802 is used in every interventions
Thanks ;)
This will show 1 line intervention - products. Is this you are expecting for?
select interventions.nointerv, products.reference
from interventions
inner join replacements on interventions.nointerv = replacements.nointerv
inner join products on replacements.reference = products.reference;
This one?
select products.reference, products.designation
from interventions
inner join replacements on interventions.nointerv = replacements.nointerv
inner join products on replacements.reference = products.reference
group by products.reference, products.designation
having count(*) = (select count(*) from interventions);
Your question is hard to follow. If I interpret it as all nointerv in replacements whose reference contains all products, then:
select nointerv
from replacements r
group by nointerv
having count(distinct reference) = (select count(*) from products);

JOIN ON SQL syntax

I am taking my first database class and need some info on what I need to change for my script to process. Currently I have 2 tables, an "orders" table and a "customers" table and this is how they are coded.
CREATE TABLE customers (
customer_id INT ,
customer_first_name VARCHAR(20),
customer_last_name VARCHAR(20) NOT NULL,
customer_address VARCHAR(50) NOT NULL,
customer_city VARCHAR(20) NOT NULL,
customer_state CHAR(2) NOT NULL,
customer_zip CHAR(5) NOT NULL,
customer_phone CHAR(10) NOT NULL,
customer_fax CHAR(10),
CONSTRAINT customers_pk
PRIMARY KEY (customer_id)
);
CREATE TABLE order (
order_id INT NOT NULL,
customer_id INT NOT NULL,
order_date DATE NOT NULL,
shipped_date DATE,
employee_id INT,
CONSTRAINT orders_pk
PRIMARY KEY (order_id),
CONSTRAINT orders_fk_customers
FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
CONSTRAINT orders_fk_employees
FOREIGN KEY (employee_id) REFERENCES employees (employee_id)
);
My script to join these two tables together is as follows:
SELECT or.order_id, or.order_date, or.customer_city,
cu.customer_first_name, cu.customer_last_name
FROM orders or INNER JOIN customers cu
ON or.customer_first_name = cu.customer_first_name
AND or.customer_last_name = cu.customer_last_name;
Now obviously, I know it is incorrect and may have multiple errors, so be gentle. I would love to know what I can do to make it work. Please advise.
Two things:
Don't use or as an alias. That's a reserved word.
Join by the foreign key.
The query should look like:
SELECT o.order_id, o.order_date, cu.customer_city,
cu.customer_first_name, cu.customer_last_name
FROM orders o
INNER JOIN customers cu
on o.customer_id = cu.customer_id
You can join your tables on the ID numbers, and you won't have to worry about what happens when multiple people have the same name.
Use this instead:
FROM orders ord INNER JOIN customers cu
ON ord.order_id = cu.customer_id
Your select statement can remain as it is. I also re-aliased according to the comment from Error_2646.
Using a field that is a primary key in one of your tables is also better practice than using non-key fields, when possible.

How to create relationship between two non primary key entity in SQL Server

I have few tables where I need to link Patient card ID (PID) of table patient where primary key is patient_id with the PID field of other tables... how can I do that? help!
you can join them like
SELECT *
FROM [Patient] p
INNER JOIN [OtherTable] ot
ON p.pid = ot.patient_id;
You can use Foreign Keys
CREATE TABLE T
(
any_primary_key INT PRIMARY KEY,
[other attributes],
patient_id,
FOREIGN KEY (patiend_id) REFERENCES Patients.patient_id
)
Where Patients is a table that has the original patient_id which has to be declared as unique.