I have this dictionary thing and the table with translations. I can do a nice select using it with SQLite
SELECT e.slug,
en.title,
en.locale
FROM entities AS e
LEFT JOIN (
locales AS en,
entity_locales AS el
) ON (
el.entity_id = e.id
AND el.locale_id = en.id
AND en.locale == 'en'
)
That produces:
present, translation, en
missing, NULL, NULL
But I can't convert it to Postgres because I don't understand what is going on when you specify more than one table in LEFT JOIN in SQLite:
SELECT e.slug,
en.title,
en.locale
FROM entities e
LEFT JOIN entity_locales el ON (el.entity_id = e.id)
JOIN locales en ON (
el.locale_id = en.id
AND en.locale = 'en'
)
Produces only
present, translation, en
Is there a way to make it work?
Database structure in SQLite format:
CREATE TABLE IF NOT EXISTS "entities" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"slug" varchar
);
CREATE TABLE IF NOT EXISTS "entity_locales" (
"entity_id" integer,
"locale_id" integer
);
CREATE TABLE IF NOT EXISTS "locales" (
"id" integer PRIMARY KEY AUTOINCREMENT NOT NULL,
"title" varchar,
"locale" varchar
);
insert into entities(id, slug) values(1, 'present');
insert into entities(id, slug) values(2, 'missing');
insert into locales(id, title, locale) values(1, 'translation', 'en');
insert into entity_locales(entity_id, locale_id) values(1, 1);
You are using a left join only to the second table, and then you are using an inner join to the third. You need to use a left join to the product of the inner join between the second and third table.
Try this instead:
SELECT e.slug,
en.title,
en.locale
FROM entities e
LEFT JOIN
(
entity_locales el
JOIN locales en ON (
el.locale_id = en.id
AND en.locale = 'en'
)
) ON (el.entity_id = e.id)
btw, your initial script mixes implicit and explicit joins. I would advise against using implicit joins since explicit joins are a standard part of SQL for over 25 years now.
Related
With postgreSQL I would like to ...
Goal: I would like to do a subtraction operation on two tables that were joined (INNER JOIN) and grouped (GROUP BY) before.
Below is a minimal reproducible script that I hope will work for you.
In this script I create the tables, insert data, show what I expect with a workaround. And I show you what I'd like to do in a single SQL operation (unsuccessfully).
I hope you understand and thank you for your attention.
/* Scrip minimal reproducible example (Script_mre)
* Data: 04/01/2023
* Autor: Carlos Antonio Zarzar */
-- Purpose: I would like to do a subtraction operation on two tables that
-- were joined (INNER JOIN) and grouped (GROUP BY) before.
-------------------#-------------------#-------------------#-------------------#
--## Creating database and tables ##--
-- Building Database
CREATE DATABASE db_racao;
-- TABLE racao
CREATE TABLE racao(
id_racao SERIAL PRIMARY KEY NOT NULL,
tamanho INT NOT NULL,
tipo VARCHAR(20) NOT NULL,
proteina INT NOT NULL
);
-- TABLE compra_racao
CREATE TABLE compra_racao(
id_comp_racao SERIAL PRIMARY KEY NOT NULL,
id_racao SERIAL NOT NULL REFERENCES racao(id_racao),
valor_uni NUMERIC NOT NULL,
quantidade REAL NOT NULL,
valor_entrada NUMERIC NOT NULL,
validade DATE NOT NULL,
cod_lote INT NOT NULL
);
-- TABLE saida_racao
CREATE TABLE saida_racao(
id_saida_racao SERIAL PRIMARY KEY NOT NULL,
quantidade REAL NOT NULL,
valor_saida NUMERIC NOT NULL,
data_saida TIMESTAMP NOT NULL,
id_comp_racao SERIAL NOT NULL REFERENCES compra_racao(id_comp_racao),
id_racao SERIAL NOT NULL REFERENCES racao(id_racao)
);
-------------------#-------------------#-------------------#-------------------#
--## Inserting data into tables ##--
-- TABLE racao
INSERT INTO racao(tamanho,tipo,proteina)
VALUES
(5,'alevino',48),
(10,'engorda',38),
(25,'prime',42),
(5,'alevino',48);
-- TABLE compra_racao
INSERT INTO compra_racao(id_racao,valor_uni,quantidade,valor_entrada,validade,cod_lote)
VALUES
(1,2.5,2000,5000,'2025-01-01',123),
(2,3.4,1000,3400,'2025-01-01',321),
(3,4.0,1000,4000,'2025-01-01',654),
(1,2.5,4000,10000,'2025-01-01',456),
(2,3.4,2000,6800,'2025-01-01',987),
(3,4.0,1500,6000,'2025-01-01',789),
(4,2.5,2500,6250,'2025-01-01',789);
-- TABLE saida_racao
INSERT INTO saida_racao(quantidade,valor_saida,data_saida,id_comp_racao,id_racao)
VALUES
(2000,5000,'2022-03-05 00:00:00',1,1),
(1000,3400,'2022-05-08 00:00:00',2,2),
(500,1700,'2022-09-25 00:00:00',3,3),
(100,340,'2022-09-25 00:00:00',3,3),
(1000,2500,'2023-02-10 00:00:00',4,1),
(1000,2500,'2023-03-30 00:00:00',5,2),
(1000,2500,'2023-04-05 00:00:00',6,3),
(575,1437.5,'2023-11-10 00:00:00',4,1),
(1525,3812.5,'2023-12-15 00:00:00',4,1),
(1000,2500,'2023-12-20 00:00:00',7,4),
(1200,3000,'2023-12-20 00:00:00',7,4);
-------------------#-------------------#-------------------#-------------------#
--## Making the queries ##--
/* The problem:
* I would like to subtract two resulting tables, the "Entrada" table and the "Saida" table.
* Each tables are grouped by id.racao.*/
/* Not an "elegant" solution, i.e. a workaround:
* I transform each table resulting from the operation into another table (of the MATERIALIZED VIEW type).
* And then I do the third operation which is the query of the "Estoque" table*/
-- MATERIALIZED VIEW Entrada
CREATE MATERIALIZED VIEW view_entrada AS
SELECT r.id_racao, SUM(cr.quantidade) AS "entrada", SUM(cr.valor_entrada) AS "valor_entrada"
FROM racao AS r
INNER JOIN compra_racao AS cr
ON r.id_racao = cr.id_racao
GROUP BY r.id_racao
ORDER BY r.id_racao
WITH DATA;
-- MATERIALIZED VIEW Saida
CREATE MATERIALIZED VIEW view_saida AS
SELECT r.id_racao, SUM(sr.quantidade) AS "saida", SUM(sr.valor_saida) AS "valor_saida"
FROM racao AS r
INNER JOIN saida_racao AS sr
ON r.id_racao = sr.id_racao
GROUP BY r.id_racao
ORDER BY r.id_racao
WITH DATA;
-- And finally the query with the "Estoque" Table (joining the two "Entrada" and "Saida" by group)
-- Estoque
SELECT id_racao, ve.entrada - vs.saida AS quant_total, ve.valor_entrada - vs.valor_saida AS valor_total
FROM view_entrada AS ve
INNER JOIN view_saida AS vs
USING (id_racao);
-- This is the result I expect.
-------------------#-------------------#-------------------#-------------------#
-- Now what I would like to do is do all the operations at once and then
-- make the resulting table a MATERIALIZED VIEW for queries.
-- An idea of what you'd like (may help):
SELECT
(SELECT r.id_racao, SUM(cr.quantidade) FROM racao AS r
INNER JOIN compra_racao AS cr
ON r.id_racao = cr.id_racao
GROUP BY r.id_racao)
-
(SELECT r.id_racao, SUM(sr.quantidade)
FROM racao AS r
INNER JOIN saida_racao AS sr
ON r.id_racao = sr.id_racao
GROUP BY r.id_racao)
You can do it this way (Result here)
with entrada as (
SELECT r.id_racao, SUM(cr.quantidade) AS qty, SUM(cr.valor_entrada) AS valor
FROM racao AS r
INNER JOIN compra_racao AS cr
ON r.id_racao = cr.id_racao
GROUP BY r.id_racao
ORDER BY r.id_racao),
salida as (
SELECT r.id_racao, SUM(sr.quantidade) AS qty, SUM(sr.valor_saida) AS valor
FROM racao AS r
INNER JOIN saida_racao AS sr
ON r.id_racao = sr.id_racao
GROUP BY r.id_racao
ORDER BY r.id_racao)
select
coalesce(e.id_racao,s.id_racao) as id, coalesce(e.qty,0) - coalesce(s.qty,0) AS quant_total,
coalesce(e.valor,0) - coalesce(s.valor,0) AS valor_total
from
entrada e left join salida s on e.id_racao = s.id_racao
I am trying to create a view which will be a base for Excel export in API. Basically, what it contains is information about particular projects. To said projects calculations can be added (it all happens on the form on frontend). Those calculations are called EBIT, EBIT+ and OVI. User can add either one, two or all of them, so for example there will be projects with only EBIT, but also projects with only for example EBIT, but also only with EBIT+ and OVI. View needs to return the project information with all chosen calculations in one row, so because some type of calculations wont be chosen by user there needs to be a type safety as well.
Code of my view:
CREATE VIEW [Signoff].[ExecelReport_uvw]
AS SELECT
project.ProjectName,
project.CreatedOn,
project.ProjectId,
subCategory.SubCategoryName,
projectStatus.StatusName,
overallCategory.CategoryName,
projectUserResponsible.UserName,
valueImprovementType.ValueImprovementTypeName,
OVI.OverallImprovementTypeName,
project.NameOfSuplier,
improvementCalculation.Baseline,
improvementCalculation.ImpactValue,
project.ContractStartDate,
project.ContractEndDate,
userbusinessController.UserName as businessControllerName,
businessControllerStatus.ApprovalStatusName businessControllerStatus,
userbusinesOwner.UserName as businessOwnerName,
businesOwnerStatus.ApprovalStatusName as businessOwnerStatus,
userbusinessCFO.UserName as businessCFOName,
businessCFOStatus.ApprovalStatusName as businessCFOStatus,
project.IsEbitda,
improvementCalculation.EBITDA
FROM [Signoff].[Project] as project
LEFT JOIN [Signoff].[OverallImprovementType] as OVI on project.OverallImprovementTypeId = OVI.OverallImprovementTypeId
LEFT JOIN [Signoff].[SubCategory] as subCategory on project.GPSubCategory = subCategory.SubCategoryId
LEFT JOIN [Signoff].[Category] as overallCategory on project.GPCategory = overallCategory.CategoryId
LEFT JOIN [Signoff].[ValueImprovementType] as valueImprovementType on project.ValueImprovementTypeId = valueImprovementType.ValueImprovementTypeId
LEFT JOIN [Signoff].[Status] as projectStatus on project.ProjectStatus = projectStatus.StatusId
LEFT JOIN [Signoff].[User] as projectUserResponsible on project.ProjectResponsible = projectUserResponsible.UserId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessControler on project.ProjectId = projectUserbusinessControler.ProjectId AND projectUserbusinessControler.ProjectRoleId = 'A36FC6CD-9ED7-4AA8-B1BE-355E48BDE25A'
LEFT JOIN [Signoff].[User] as userbusinessController on projectUserbusinessControler.ApproverId = userbusinessController.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessControllerStatus on projectUserbusinessControler.ApprovalStatusId = businessControllerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessOwner on project.ProjectId = projectUserbusinessOwner.ProjectId AND projectUserbusinessOwner.ProjectRoleId = 'E1E23E4F-1CA4-4869-9387-43CEDAEBBBB0'
LEFT JOIN [Signoff].[User] as userbusinesOwner on projectUserbusinessOwner.ApproverId = userbusinesOwner.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businesOwnerStatus on projectUserbusinessOwner.ApprovalStatusId = businesOwnerStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectUser] as projectUserbusinessCFO on project.ProjectId = projectUserbusinessCFO.ProjectId AND projectUserbusinessCFO.ProjectRoleId = 'DA17CF66-1D61-460E-BF87-5D86744DF22A'
LEFT JOIN [Signoff].[User] as userbusinessCFO on projectUserbusinessCFO.ApproverId = userbusinessCFO.UserId
LEFT JOIN [Signoff].[ApprovalStatus] as businessCFOStatus on projectUserbusinessCFO.ApprovalStatusId = businessCFOStatus.ApprovalStatusId
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
Improvement calculation table:
CREATE TABLE [Signoff].[ImprovementCalculation]
(
[ImprovementCalculationId] INT NOT NULL IDENTITY,
[Baseline] INT NOT NULL,
[TotalSpend] INT NOT NULL,
[ImpactValue] INT NOT NULL,
[ImpactPercentage] INT NOT NULL,
[EBITDA] INT NOT NULL,
[CalculationType] VARCHAR (255) NOT NULL
)
GO
ALTER TABLE [Signoff].[ImprovementCalculation]
ADD CONSTRAINT [PK_ImprovemntCalculation] PRIMARY KEY([ImprovementCalculationId]);
GO
Project Improvement Calculation table:
CREATE TABLE [Signoff].[ProjectImprovementCalculation]
(
[ProjectImprovementCalculationId] INT NOT NULL IDENTITY,
[ProjectId] UNIQUEIDENTIFIER NOT NULL,
[ImprovementCalculationId] INT NOT NULL,
)
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT [PK_ProjectImprovementCalculation] PRIMARY KEY([ProjectImprovementCalculationId]);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ProjectProjectImprovementCalculation
FOREIGN KEY (ProjectId) REFERENCES [Signoff].[Project](ProjectId);
GO
ALTER TABLE [Signoff].[ProjectImprovementCalculation]
ADD CONSTRAINT FK_ImprovementCalculationProjectImprovementCalculation
FOREIGN KEY (ImprovementCalculationId) REFERENCES [Signoff].[ImprovementCalculation](ImprovementCalculationId);
GO
Just in case, although I don't think it's needed, the project table:
CREATE TABLE [Signoff].[Project]
(
[ProjectId] UNIQUEIDENTIFIER NOT NULL DEFAULT (NEWID()),
[ProjectName] NVARCHAR(50) NOT NULL,
[LegalEntity] UNIQUEIDENTIFIER NOT NULL,
[ValueImprovementTypeId] INT NOT NULL,
[OverallImprovementTypeId] INT NOT NULL,
[NameOfSuplier] NVARCHAR(50) NOT NULL,
[ContractStartDate] DATE NOT NULL,
[ContractEndDate] DATE NOT NULL,
[GPCategory] UNIQUEIDENTIFIER NOT NULL,
[GPSubCategory] UNIQUEIDENTIFIER NOT NULL,
[ProjectResponsible] UNIQUEIDENTIFIER NOT NULL,
[ProjectNumber] INT,
[FullProjectNumber] VARCHAR(55),
[ProjectStatus] UNIQUEIDENTIFIER NOT NULL DEFAULT '05c2f392-8b69-4915-a166-c4418889f9e8',
[IsCanceled] BIT NULL DEFAULT 0,
[IsEbitda] BIT NOT NULL DEFAULT 0,
[CreatedOn] DATETIME NOT NULL DEFAULT SYSDATETIME()
)
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [PK_Project] PRIMARY KEY([ProjectId]);
GO
ALTER TABLE [Signoff].[Project]
ADD CONSTRAINT [FK_ProjectStatus] FOREIGN KEY ([ProjectStatus]) REFERENCES [Signoff].[Status]([StatusId]);
GO
I have so came up with this solution, but it returns every single calculation in a different row in a table, and I want all calculations be in a single row with a project, so not what I am looking for:
LEFT JOIN [Signoff].[ProjectImprovementCalculation] as projectImprovementCalculation on project.ProjectId = projectImprovementCalculation.ProjectId
LEFT JOIN [Signoff].[ImprovementCalculation] as improvementCalculation on projectImprovementCalculation.ImprovementCalculationId = improvementCalculation.ImprovementCalculationId
Does anyone knows how to do it? Or I am approaching a problem from completely wrong way? If the information I have written is a bit chaotic, something isn't understandable, I can rephrase it.
I will assume that the available CalculationType values is fixed, that each project will have at most one improvement calculation per type, and that you wish to define fixed dedicated columns for BaseLine and ImpactValue each calculation type.
One approach is to use nested joins that will effectively LEFT JOIN the INNER JOINed combination of ProjectImprovementCalculation and ImprovementCalculation once for each calculation type. The results of each can then be referenced individually in the final select list.
Something like:
SELECT ...
IC_AAA.BaseLine, IC_AAA.ImpactValue,
IC_BBB.BaseLine, IC_BBB.ImpactValue,
...
FROM ...
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_AAA
JOIN Signoff.ImprovementCalculation as IC_AAA
ON IC_AAA.ImprovementCalculationId = PIC_AAA.ImprovementCalculationId
AND IC_AAA.CalculationType = 'AAA'
ON PIC_AAA.ProjectId = project.ProjectId
LEFT JOIN Signoff.ProjectImprovementCalculation as PIC_BBB
JOIN Signoff.ImprovementCalculation as IC_BBB
ON IC_BBB.ImprovementCalculationId = PIC_BBB.ImprovementCalculationId
AND IC_BBB.CalculationType = 'BBB'
ON PIC_BBB.ProjectId = project.ProjectId
...
The syntax is somewhat odd with two JOINs followed by two ON clauses. It would be clearer if parentheses were allowed, but (as far as I know) that is not part of the syntax.
There are several alternatives that accomplish the same. The following uses an OUTER APPLY:
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'AAA'
WHERE PIC.ProjectId = project.ProjectId
) AAA
OUTER APPLY (
SELECT IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
AND IC.CalculationType = 'BBB'
WHERE PIC.ProjectId = project.ProjectId
) BBB
...
Using a Common Table Expression (CTE) can reduce some of the duplication as well as making the query a bit more readable.
;WITH ImprovementCTE AS (
SELECT PIC.ProjectId, IC.*
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
)
SELECT ...
AAA.BaseLine, AAA.ImpactValue,
BBB.BaseLine, BBB.ImpactValue,
...
FROM ...
LEFT JOIN ImprovementCTE AAA
ON AAA.ProjectId = project.ProjectId
AND AAA.CalculationType = 'AAA'
LEFT JOIN ImprovementCTE BBB
ON BBB.ProjectId = project.ProjectId
AND BBB.CalculationType = 'BBB'
...
You might also try using conditional aggregation in a single CROSS APPLY:
SELECT ...
IC.BaseLineAAA, IC.ImpactValueAAA,
IC.BaseLineBBB, IC.ImpactValueBBB,
...
FROM ...
CROSS APPLY (
SELECT
BaseLineAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.BaseLine),
ImpactValueAAA = SUM(CASE WHEN IC.CalculationType = 'AAA' THEN IC.ImpactValue),
BaseLineBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.BaseLine),
ImpactValueBBB = SUM(CASE WHEN IC.CalculationType = 'BBB' THEN IC.ImpactValue),
...
FROM Signoff.ProjectImprovementCalculation as PIC
JOIN Signoff.ImprovementCalculation as IC
ON IC.ImprovementCalculationId = PIC.ImprovementCalculationId
WHERE PIC.ProjectId = project.ProjectId
) IC
I expect there are additional approaches such as using a PIVOTs.
If the above appears to suit your needs, you should still run tests and examine the execution plans to see which performs best. Some may have a tendency to retrieve all ImprovementCalculation rows even when a subset of projects are selected.
To handle missing calculation types, you can use the ISNULL() function to provide a default. If you need to force a blank value in an otherwise numeric result, you might need to use something like ISNULL(CONVERT(VARCHAR(50), result), '').
This is my query
SELECT p.book FROM customers_books p
INNER JOIN books b ON p.book = b.id
INNER JOIN bookprices bp ON bp.book = p.book
WHERE b.status = 'PUBLISHED' AND bp.currency_code = 'GBP'
AND p.book NOT IN (SELECT cb.book FROM customers_books cb WHERE cb.customer = 1)
GROUP BY p.book, p.created_date ORDER BY p.created_date DESC
This is the data in my customers_books table,
I expect only 8,6,1 of books IDs to return but query is returning 8,6,1,1
table structures are here
CREATE TABLE "public"."customers_books" (
"id" int8 NOT NULL,
"created_date" timestamp(6),
"book" int8,
"customer" int8,
);
CREATE TABLE "public"."books" (
"id" int8 NOT NULL,
"created_date" timestamp(6),
"status" varchar(255) COLLATE "pg_catalog"."default",
)
CREATE TABLE "public"."bookprices" (
"id" int8 NOT NULL,
"currency_code" varchar(255) COLLATE "pg_catalog"."default",
"book" int8
)
what do you think I am doing wrong here.
I really dont want to use p.created_date in group by but I was forced to use because of order by
You have too many joins in the outer query:
SELECT b.book
FROM books b INNER JOIN
bookprices bp
ON bp.book = p.book
WHERE b.status = 'PUBLISHED' AND bp.currency_code = 'GBP' AND
NOT EXISTS (SELECT 1
FROM customers_books cb
WHERE cb.book = p.book AND cb.customer = 1
) ;
Note that I replaced the NOT IN with NOT EXISTS. I strongly, strongly discourage you from using NOT IN with a subquery. If the subquery returns any NULL values, then NOT IN returns no rows at all. It is better to sidestep this issue just by using NOT EXISTS.
So, I have the following code that updates a language string table, based on an id, and a language code. If I perform a SELECT using the same from expression, it selects just one row. If I do update, it updates all rows. Where am I going wrong with this?
UPDATE shopmaster.catalog_lang SET shortname='TEST'
FROM shopmaster.catalog_lang cl LEFT JOIN shopmaster.lang l ON cl.langid=l.langid
WHERE cl.catalogid=7 AND l.code='fr';
Here's the definition of the two tables:
CREATE TABLE IF NOT EXISTS shopmaster.lang(
langid SERIAL,
name TEXT,
code TEXT,
active BOOLEAN,
donotdelete BOOLEAN,
PRIMARY KEY (langid)
CREATE TABLE IF NOT EXISTS shopmaster.catalog_lang(
catalogid INT references shopmaster.catalog(catalogid),
langid INT references shopmaster.lang(langid),
title TEXT,
shortname TEXT,
dirname TEXT,
PRIMARY KEY (catalogid, langid)
);
Don't repeat the table being updated in the FROM. So:
UPDATE shopmaster.catalog_lang cl
SET shortname = 'TEST'
FROM shopmaster.lang l
WHERE cl.langid = l.langid AND cl.catalogid = 7 AND l.code = 'fr';
In Postgres each reference to the table is separate. Your update is equivalent to this SELECT:
SELECT . . .
FROM shopmaster.catalog_lang CROSS JOIN
shopmaster.catalog_lang cl LEFT JOIN
shopmaster.lang l
ON cl.langid = l.langid
WHERE cl.catalogid = 7 AND l.code = 'fr';
And this is definitely not what you intend.
I use generalisation/specialize table Zadavatel (which contains primary key) as either table Sukromna_osoba or Firma (both contains foreign key that points on Zadavatel).
I need to select Sukromna_osoba table if Sukromna_osoba.meno = 'string' exists or Firma table if Firma.nazov_firmy = 'string' exists, both if both conditions are true. I also need this to be in one select.
CREATE TABLE Zadavatel (
id_zadavatela INTEGER,
adresa VARCHAR(25)
);
CREATE TABLE Sukromna_osoba (
id_sukromnej_osoby INTEGER,
meno VARCHAR(20),
mobil INTEGER,
email VARCHAR(20)
);
CREATE TABLE Firma (
id_firmy INTEGER,
nazov_firmy VARCHAR(20),
ico INTEGER,
bankove_spojenie INTEGER
);
id_zadavatela is primary key, and id_sukromnej_osoby and id_firmy are foreign keys which points at id_zadavatela.
I tried something like this:
SELECT PR.id_projektu, PR.popis, ZAD.id_zadavatela, FI.nazov_firmy
FROM Projekt PR JOIN Zamestnanec ZAM ON PR.manazer = ZAM.osobne_cislo
JOIN Zadavatel ZAD ON PR.zadavatel = ZAD.id_zadavatela
JOIN Firma FI ON ZAD.id_zadavatela = FI.id_firmy
WHERE ZAM.meno = 'Jan Novák' OR (
SELECT PR1.id_projektu, PR1.popis, ZAD1.id_zadavatela, SO1.meno
FROM Projekt PR1 JOIN Zamestnanec ZAM1 ON PR1.manazer = ZAM1.osobne_cislo
JOIN Zadavatel ZAD1 ON PR1.zadavatel = ZAD1.id_zadavatela
JOIN Sukromna_osoba SO1 ON ZAD1.id_zadavatela = SO1.id_sukromnej_osoby
WHERE ZAM1.meno = 'Jan Novák'
)
Since you do not know if it's a firm or a person, you could use left outer join on both, like this:
SELECT PR.id_projektu, PR.popis, ZAD.id_zadavatela, FI.nazov_firmy, SO.meno
FROM Projekt PR
JOIN Zamestnanec ZAM ON PR.manazer = ZAM.osobne_cislo
JOIN Zadavatel ZAD ON PR.zadavatel = ZAD.id_zadavatela
LEFT OUTER JOIN Firma FI ON ZAD.id_zadavatela = FI.id_firmy
LEFT OUTER JOIN Sukromna_osoba SO ON ZAD.id_zadavatela = SO.id_sukromnej_osoby
WHERE ZAM.meno = 'Jan Novák'
One of the two result columns, nazov_firmy or meno, will be NULL.