I have three tables:
CREATE TABLE [dbo].[Data]
(
[PorID] [int] NOT NULL,
[HourS] [int] NOT NULL
)
CREATE TABLE [dbo].[TimeData]
(
[HId] [bigint] NOT NULL,
[HName] [varchar](50) NOT NULL,
[HHour] [int] NOT NULL
)
CREATE TABLE [dbo].PortInfo
(
[Id] [bigint] NOT NULL,
[PortName] [varchar](50) NOT NULL
)
Even if the port is not present in the Data table it should return rows for all port in PortInfo table. Similarly, it should always return 24 records for each port. The result should display all ports for each record even if doesn't exist within the Data table.
Updated Answer
Based on what you are telling me in the comments and me filling in some blanks, this is what I assume you are looking for. This will produce a record for every hour, for every port.
SELECT
td.HHour,
td.HName,
pi.Id,
pi.PortName,
d.PorID,
d.HourS
FROM
dbo.TimeData td
FULL OUTER JOIN
dbo.PortInfo pi
ON (1 = 1)
LEFT OUTER JOIN
dbo.Data d
ON (d.PorID = pi.Id)
AND (d.HourS = td.HHour)
Output:
Some feedback to make this process easier. Share your schema (relationships) and/or some sample data. Also, consider creating more logical/intuitive names for your columns so that relationships and content may be implied.
Original Answer
This sounds like what you are looking for. The query below will return all port information (from PortInfo) even if its Id is not in the Data table (PorId). This is done by using a LEFT JOIN onto the PortInfo table.
SELECT
po.Id,
po.PortName,
d.HourS
FROM
dbo.PortInfo po
LEFT JOIN
dbo.Data d
ON (d.PorID = po.Id)
Now, you don't mention the how or if the 3rd table TimeData should be used, but if you wanted that information in your result as well, you can simply LEFT JOIN that as well:
SELECT
po.Id,
po.PortName,
d.HourS,
td.HName,
td.HHour
FROM
dbo.PortInfo po
LEFT JOIN
dbo.Data d
ON (d.PorID = po.Id)
LEFT JOIN
dbo.TimeData td
ON (td.HId = d.HourS) -- I assume this is the link, you may need to update if not.
Related
I want to enter in a query the subtract between two columns in different tables it keeps saying error ...
SELECT FlightDate,
Plane,
Destination,
Capacity
FROM
FlightSchedule,
Routes,
Aircrafts
WHERE
FlightSchedule.RID=Routes.RouteID
AND FlightSchedule.Plane=Aircrafts.AcID
AND (SELECT SUM(Capacity)
FROM Aircrafts)
-
(SELECT Class , count(*)
FROM Tickets);
I would split this up into 2 parts. First get the data you need, then perform the math. You are also using old SQL syntax. You should re-format using the new JOIN syntax. It's also easier to read.
1st declare a table to hold you flight schedule and aircraft info.
Declare #AIRCRAFTCAPACITY Table
(
[FlightDate] [datetime] NOT NULL,
[Plane] [varchar](50) NOT NULL,
[Destination] [varchar](50) NOT NULL,
[Capacity] [INT] NOT NULL,
[NoOfSeatsRemaining] [INT] NULL
);
Then insert the data you need.
INSERT #AIRCRAFTCAPACITY
(
[FlightDate],
[Plane],
[Destination],
[Capacity]
)
SELECT FS.FlightDate,
A.Plane,
FS.Destination,
A.Capacity
FROM
FlightSchedule FS
INNER
JOIN Routes R
ON
FS.RID = R.RouteID
INNER
JOIN Aircrafts A
ON
FS.Plane = A.AcID
Now perform the math to calculate the remaining capacity. I've made an assumption that you are doing this for a particular route. But I'm sure you can adjust your SQL accordingly.
UPDATE #AIRCRAFTCAPACITY
SET
[NoOfSeatsRemaining] = [Capacity] - T.TICKETS_SOLD
FROM
#AIRCRAFTCAPACITY A
INNER
JOIN
(
SELECT ROUTEID, COUNT(ROUTEID) AS TICKETS_SOLD
FROM
Tickets T1
WHERE
T1.ROUTEID = A.ROUTEID
GROUP
BY ROUTEID
) T
ON
A.ROUTEID = T.ROUTEID
Apolgies if the syntax is a little off as it's hard to construct SQL when you dont have the underlying tables.
But hopefully it will help.
The query is wrong on multiple levels.
First of all, you cannot put the details of SELECT capacity as a sub query under WHERE. The WHERE clause is for conditional parameters.
Try this:
WITH VACANCY as (SELECT SUM(Capacity) FROM Aircrafts) - (SELECT Count(*) FROM Tickets)
SELECT FlightDate,Plane, Destination, Vacancy
FROM FlightSchedule,Routes,Aircrafts
WHERE FlightSchedule.RID=Routes.RouteID AND FlightSchedule.Plane=Aircrafts.AcID;
You also need to a condition for the select count for tickets but I don't know the schema of tickets so...
How can I select a field that is in a where not exists subquery into the main query.
These 2 tables are not related in terms of foreign keys etc and I have not control over.
Let's take a fictious sample I have 2 tables "Category-Order"
CREATE TABLE [dbo].[Category](
[Id] [bigint] NOT NULL,
[Name] [varchar](255) NULL,
[OrderName] [varchar](50) NULL,
[CategoryType] [varchar](50) NULL
CREATE TABLE [dbo].[Order](
[OrderId] [bigint] NOT NULL,
[OrderName] [varchar](50) NULL
)
Given a query like below ,How can I rewrite the below query so that I can have CategoryType Selected as well?
At the moment I get the following error:
"The multi-part identifier "C.CategoryType" could not be bound."
INSERT INTO Category(Name,OrderName,CategoryType)
SELECT DISTINCT 'Fruit',O.OrderName , C.CategoryType
FROM [Order]O
WHERE NOT EXISTS(
SELECT 1
FROM Category c
WHERE c.Name='Fruit'
AND C.OrderName=O.OrderName)
Or could you tell me the equivalent of the above query using a join and eliminating the where not exists
Many thanks for any suggestions
You cannot use in the main query a table of the subquery.
You can do that :
INSERT INTO Category(Name,OrderName,CategoryType)
SELECT DISTINCT 'Fruit', O.OrderName , c.CategoryType
FROM [Order]O
LEFT JOIN Category c
ON c.OrderName=O.OrderName
LEFT JOIN Category c2
ON c2.OrderName=O.OrderName
AND c2.Name = 'Fruit'
WHERE
c.OrderName IS NOT NULL
AND c2.OrderName IS NULL
Or with ur exemple :
INSERT INTO Category(Name,OrderName,CategoryType)
SELECT DISTINCT 'Fruit',O.OrderName , Cat.CategoryType
FROM [Order]O
LEFT JOIN Category cat
ON cat.OrderName=O.OrderName
WHERE NOT EXISTS(
SELECT 1
FROM Category c
WHERE c.Name='Fruit'
AND C.OrderName=O.OrderName)
Let's say I have three tables A, B, and C. Each has two columns: a primary key and some other piece of data. They each have the same number of rows. If I JOIN A and B on the primary key, I should end up with the same number of rows as are in either of them (as opposed to A.rows * B.rows).
Now, if I JOIN A JOIN B with C, why do I end up with duplicate rows? I have run into this problem on several occasions and I do not understand it. It seems like it should produce the same result as JOINing A and B since it has the same number of rows but, instead, duplicates are produced.
Queries that produce results like this are of the format
SELECT *
FROM M
INNER JOIN S
on M.mIndex = S.mIndex
INNER JOIN D
ON M.platformId LIKE '%' + D.version + '%'
INNER JOIN H
ON D.Name = H.Name
AND D.revision = H.revision
Here are schemas for the tables. H contains is a historic table containing everything that was ever in D. There are many M rows for each D and one S for each M.
Table M
[mIndex] [int] NOT NULL PRIMARY KEY,
[platformId] [nvarchar](256) NULL,
[ip] [nvarchar](64) NULL,
[complete] [bit] NOT NULL,
[date] [datetime] NOT NULL,
[DeployId] [int] NOT NULL PRIMARY KEY REFERENCES D.DeployId,
[source] [nvarchar](64) NOT NULL PRIMARY KEY
Table S
[order] [int] NOT NULL PRIMARY KEY,
[name] [nvarchar](64) NOT NULL,
[parameters] [nvarchar](256) NOT NULL,
[Finished] [bit] NOT NULL,
[mIndex] [int] NOT NULL PRIMARY KEY,
[mDeployId] [int] NOT NULL PRIMARY KEY,
[Date] [datetime] NULL,
[status] [nvarchar](10) NULL,
[output] [nvarchar](max) NULL,
[config] [nvarchar](64) NOT NULL PRIMARY KEY
Table D
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[branch] [nvarchar](64) NOT NULL,
[revision] [int] NOT NULL,
[version] [nvarchar](64) NOT NULL,
[path] [nvarchar](256) NOT NULL
Table H
[IdDeploy] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](64) NOT NULL,
[version] [nvarchar](64) NOT NULL,
[path] [nvarchar](max) NOT NULL,
[StartDate] [datetime] NOT NULL,
[EndDate] [datetime] NULL,
[Revision] [nvarchar](64) NULL,
I didn't post the tables and query initially because I am more interested in understanding this problem for myself and avoiding it in the future.
When you have related tables you often have one-to-many or many-to-many relationships. So when you join to TableB each record in TableA many have multiple records in TableB. This is normal and expected.
Now at times you only need certain columns and those are all the same for all the records, then you would need to do some sort of group by or distinct to remove the duplicates. Let's look at an example:
TableA
Id Field1
1 test
2 another test
TableB
ID Field2 field3
1 Test1 something
1 test1 More something
2 Test2 Anything
So when you join them and select all the files you get:
select *
from tableA a
join tableb b on a.id = b.id
a.Id a.Field1 b.id b.field2 b.field3
1 test 1 Test1 something
1 test 1 Test1 More something
2 another test 2 2 Test2 Anything
These are not duplicates because the values of Field3 are different even though there are repeated values in the earlier fields. Now when you only select certain columns the same number of records are being joined together but since the columns with the different information is not being displayed they look like duplicates.
select a.Id, a.Field1, b.field2
from tableA a
join tableb b on a.id = b.id
a.Id a.Field1 b.field2
1 test Test1
1 test Test1
2 another test Test2
This appears to be duplicates but it is not because of the multiple records in TableB.
You normally fix this by using aggregates and group by, by using distinct or by filtering in the where clause to remove duplicates. How you solve this depends on exactly what your business rule is and how your database is designed and what kind of data is in there.
If one of the tables M, S, D, or H has more than one row for a given Id (if just the Id column is not the Primary Key), then the query would result in "duplicate" rows. If you have more than one row for an Id in a table, then the other columns, which would uniquely identify a row, also must be included in the JOIN condition(s).
References:
Related Question on MSDN Forum
This might sound like a really basic "DUH" answer, but make sure that the column you're using to Lookup from on the merging file is actually full of unique values!
I noticed earlier today that PowerQuery won't throw you an error (like in PowerPivot) and will happily allow you to run a Many-Many merge. This will result in multiple rows being produced for each record that matches with a non-unique value.
Make sure your join query is correct: i was facing this issue due to
join query issue
/****** Script for command from SSMS ******/
SELECT [TransWorkShopNo]
,[TransformerCapacity].[CapacistyPrice]
,[TransformerCapacity].[HTCoilPrice]
,[TransformerCapacity].[LTCoilReclaimedPrice]
,[TransformerCapacity].[LTCoilNewPrice]
FROM [Hi-Lit-Electronics].[dbo].[TransformerData] inner join TransformerCapacity on [TransformerData].CapacistyID= [TransformerCapacity].CapacistyID
inner join TransformerItem on [TransformerData].ItemID= TransformerCapacity.ItemID
TransformerCapacity.ItemID
Here this was wrong
Ok in this example you are getting duplicates because you are joining both D and S onto M.
I assume you should be joining D.id onto S.id like below:
SELECT *
FROM M
INNER JOIN S
on M.Id = S.Id
INNER JOIN D
ON S.Id = D.Id
INNER JOIN H
ON D.Id = H.Id
use group by clause on main table id i hope it works
$this->db->group_by('products.id'); for codeigniter
I have a normalized database containing 3 tables whose DDL is this:
CREATE CACHED TABLE Clients (
cli_id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 100) PRIMARY KEY,
defmrn_id BIGINT,
lastName VARCHAR(48) DEFAULT '' NOT NULL,
midName VARCHAR(24) DEFAULT '' NOT NULL,
firstName VARCHAR(24) DEFAULT '' NOT NULL,
doB INTEGER DEFAULT 0 NOT NULL,
gender VARCHAR(1) NOT NULL);
CREATE TABLE Client_MRNs (
mrn_id BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 100) PRIMARY KEY,
cli_id INTEGER REFERENCES Clients ( cli_id ),
inst_id INTEGER REFERENCES Institutions ( inst_id ),
mrn VARCHAR(32) DEFAULT '' NOT NULL,
CONSTRAINT climrn01 UNIQUE (mrn, inst_id));
CREATE TABLE Institutions (
inst_id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 100) PRIMARY KEY,
loc_id INTEGER REFERENCES Locales (loc_id ),
itag VARCHAR(6) UNIQUE NOT NULL,
iname VARCHAR(80) DEFAULT '' NOT NULL);
The first table contains a foreign key column, defmrn_id, that is a reference to a "default identifier code" that is stored in the second table (which is a list of all identifier codes). A record in the first table may have many identifiers, but only one default identifier. So yeah, I have created a circular reference.
The third table is just normalized data from the second table.
I wanted a query that would find a CLIENT record based on matching a supplied identifier code to any of the identifier codes in CLIENT_MRNs that may belong to that CLIENT record.
My strategy was to first identify those records that matched in the second table (CLIENT_MRN) and then use that intermediate result to join to records in the CLIENT table that matched other user-supplied searching criteria. I also need to denormalize the identifier reference defmrn_id in the 1st table. Here is what I came up with...
SQL = SELECT c.*, r.mrn, i.inst_id, i.itag, i.iname
FROM Clients AS c
INNER JOIN
(
SELECT m.cli_id
FROM Client_MRNs AS m
WHERE m.mrn = ?
) AS m2 ON m2.cli_id = c.cli_id
INNER JOIN Client_MRNs AS r ON c.defmrn_id = r.mrn_id
INNER JOIN Institutions AS i USING ( inst_id )
WHERE (<other user supplied search criteria...>);
The above works, but I spent some time trying to understand why the following was NOT working...
SQL = SELECT c.*, r.mrn, i.inst_id, i.itag, i.iname
FROM Clients AS c
INNER JOIN
(
SELECT m.cli_id
FROM Client_MRNs AS m
WHERE m.mrn = ?
) AS m2 USING ( cli_id )
INNER JOIN Client_MRNs AS r ON c.defmrn_id = r.mrn_id
INNER JOIN Institutions AS i USING ( inst_id )
WHERE (<other user supplied search criteria...>);
It seems to me that the second SQL should work, but it fails on the USING clause every time. I am executing these queries against a database managed by HSQLDB 2.2.9 as the RDBMS. Is this a parsing issue in HSQLDB or is this a known limitation of the USING clause with nested queries?
You can always try with HSQLDB 2.3.0 (a release candidate).
The way you report the incomplet SQL does not allow proper checking. But there is an ovbious mistake in the query. If you have:
SELECT INST_ID FROM CLIENTS_MRS AS R INNER JOIN INSTITUTIONS AS I USING (INST_ID)
INST_ID can be used in the SELECT column list only without a table qualifier. The reason is it is no longer considered a column of either table. The same is true with common columns if you use NATURAL JOIN.
This query is accepted by version 2.3.0
SELECT c.*, r.mrn, inst_id, i.itag, i.iname
FROM Clients AS c
INNER JOIN
(
SELECT m.cli_id
FROM Client_MRNs AS m
WHERE m.mrn = 2
) AS m2 USING ( cli_id )
INNER JOIN Client_MRNs AS r ON c.defmrn_id = r.mrn_id
INNER JOIN Institutions AS i USING ( inst_id )
I wonder how better to write the following query to Microsoft SQL Server.
I have three tables: surveys, survey_presets and survey_scenes. They have the following columns:
CREATE TABLE [dbo].[surveys](
[id] [int] IDENTITY(1,1) NOT NULL,
[caption] [nvarchar](255) NOT NULL,
[creation_time] [datetime] NOT NULL,
)
CREATE TABLE [dbo].[survey_presets](
[id] [int] IDENTITY(1,1) NOT NULL,
[survey_id] [int] NOT NULL,
[preset_id] [int] NOT NULL,
)
CREATE TABLE [dbo].[survey_scenes](
[id] [int] IDENTITY(1,1) NOT NULL,
[survey_id] [int] NOT NULL,
[scene_id] [int] NOT NULL,
)
Both survey_presets and survey_scenes have foreign keys on surveys for survey_id column.
Now I want to select all surveys with the count of corresponding presets and scenes for each. Here is the "pseudo-query" of what I want:
SELECT
surveys.*,
COUNT(survey_presets, where survey_presets.survey_id = surveys.id),
COUNT(survey_scenes, where survey_scenes.survey_id = surveys.id)
FROM surveys
ORDER BY suverys.creation_time
I can do a mess with SELECT DISTINCT, JOIN, GROUP BY, etc., but I'm new to T-SQL and I doubt my query will be optimal in any sense.
I would do the counting in subqueries to avoid cartesian products. As you might have a few matching rows in presets and also a few in scenes resulting count might be multiplied. You might write simple join query and avoid the multiplication by counting distinct survey_presets.id and distinct survey_scenes.id though.
SELECT
surveys.*,
isnull(presets_count, 0) presets_count,
isnull(scenes_count, 0) scenes_count
FROM surveys
LEFT JOIN
(
SELECT survey_id,
count(*) presets_count
FROM survey_presets
GROUP BY survey_id
) presets
ON surveys.id = presets.survey_id
LEFT JOIN
(
SELECT survey_id,
count(*) scenes_count
FROM survey_scenes
GROUP BY survey_id
) scenes
ON surveys.id = scenes.survey_id
ORDER BY surveys.creation_time
How it works
You can introduce a special kind of subquery called derived table to FROM section of your query. Derived table is defined as normal query enclosed in parenthesis and followed by table alias. It cannot use any column from outer query, but can expose columns you use in ON section to join derived table to main body of the query.
In this case derived table simply count rows grouped by id; joins connect the counts to surveys.
SELECT surveys.ID, surveys.caption, surveys.creation_time,
count(survey_presets.survey_id) as survey_presets,
count(survey_scenes.survey_id) as survey_scenes
FROM surveys
LEFT OUTER JOIN survey_presets on survey_presets.survey_id = surveys.id
LEFT OUTER JOIN survey_scenes on survey_scenes.survey_id = surveys.id
GROUP BY surveys.ID, surveys.caption, surveys.creation_time
ORDER BY suverys.creation_time