This is my query:
string x1 = "SELECT unos_golub.drzava, unos_golub.spol, unos_golub.broj_goluba as broj, parovi.par_m, parovi.par_z,parovi.broj_para FROM parovi JOIN unos_golub ON (parovi.par_m=unos_golub.ID) WHERE parovi.uzgojni_par=1";
string x2 = "SELECT unos_golub.drzava, unos_golub.spol, unos_golub.broj_goluba as broj2, parovi.par_m, parovi.par_z,parovi.broj_para FROM parovi JOIN unos_golub ON (parovi.par_z=unos_golub.ID) WHERE parovi.uzgojni_par=1 ORDER BY broj_para ASC";
cmd.CommandText = x1+" UNION ALL "+x2;
In my table "parovi" there are 2 columns "par_m" and "par_z".
In second table "unos_golub" there is "ID" and some other. Now I need to get values from "par_m" and "par_z", match it in "unos_golub" and get some data.
For example, if I get par_m=91 and par_z=92, I need to find those numbers in ID of "unos_golub" and get different data for 91 and 92 and show it.
I think maybe UNION ALL could help, but it is not working.
here are my tables
table: parovi
table: unos_golub
This approach will put all on a single row for the respective "M" and "Z" values. Notice I'm joining TWICE to the "unos_golub" table, but with different aliases. So, now I have one parovi record pointing to respective "M" AND "Z" versions simultaneously. And can pull the columns from each, thus giving them aliased result column names suffixing "M" and "Z" indicating their respective origin.
SELECT
parovi.par_m,
parovi.par_z,
parovi.broj_para,
unos_M.drzava as drzava_M,
unos_M.spol as spol_M,
unos_M.broj_goluba as broj_M,
unos_Z.drzava as drzava_Z,
unos_Z.spol as spol_Z,
unos_Z.broj_goluba as broj_Z
FROM
parovi
JOIN unos_golub as unos_M
ON parovi.par_m = unos_M.ID
JOIN unos_golub as unos_Z
ON parovi.par_m = unos_Z.ID
WHERE
parovi.uzgojni_par=1";
Per your comment of wanting to show all rows, your query SHOULD only require one small change. When doing a UNION, the queries must have the same column names. You changed one o them via
unos_golub.broj_goluba as broj
vs
unos_golub.broj_goluba as broj2
which would make it fail the query. The column names are different, thus failing.
Related
I have data in two tables and I need in one query get all data and join getting data.
SELECT
kpip.PersonalName,
kpiT.Name,
kpiPR.KpiTarget,
kpiPR.KpiResultDate,
kpiPR.KpiResult
FROM KpiPersonalResult AS kpiPR join KpiPersonal as kpip
on kpiPR.KpiPersonal = kpip.Id join KpiType AS kpiT
on kpip.KpiType = kpiT.Id join MerchantAdministrators as merA
on kpiPR.KpiAdded = merA.Id and kpiPR.KpiResultDate between '2021-04-07' and '2021-04-08'
select
kpiP.PersonalName,
kpiT.Name,
kpiP.KpiTarget
from KpiPersonal as kpiP join KpiType as kpiT
on kpiP.KpiType = kpiT.Id
Based on the fast that the second query has 3 columns of the same name as the first query, I guess you mean to union them:
SELECT
kpip.PersonalName,
kpiT.Name,
kpiPR.KpiTarget,
kpiPR.KpiResultDate,
kpiPR.KpiResult
FROM
KpiPersonalResult AS kpiPR
join KpiPersonal as kpip on kpiPR.KpiPersonal = kpip.Id
join KpiType AS kpiT on kpip.KpiType = kpiT.Id
join MerchantAdministrators as merA on kpiPR.KpiAdded = merA.Id and kpiPR.KpiResultDate between '2021-04-07' and '2021-04-08'
UNION ALL
select
kpiP.PersonalName,
kpiT.Name,
kpiP.KpiTarget,
null, --put suitable default values for the other columns here
null
from
KpiPersonal as kpiP
join KpiType as kpiT on kpiP.KpiType = kpiT.Id
Unioned queries need the same number of columns. I've inserted NULL as default value for the two missing columns in the second query (relative to the first)
UNION makes a resultset grow taller. If you intended for it to grow wider, that is done via JOIN. A simple pattern for doing so is:
WITH query1 AS(
--query 1 here
), query2 AS (
--query2 here
)
SELECT * FROM query1 JOIN query2 ON ...
Side note on formatting and indenting - most people find SQL most readable when all operations that are related are at the same indent level e.g in a typical query, the SELECT FROM WHERE GROUP ORDER keywords are all at the same indent level, with the blocks that relate to them (the list of selected columns, or list of joined tables, list of where'd predicates etc) indented a level again. We also typically don't use as when aliasing tables but we do use it when aliasing columns in the SELECT
How can i merge the rows of a teachers qualification from its table to a single row and join it to another so i can search for a given condition to know if a teacher possesses the given degree/certification. Or is there a better approach other than the one i am trying to use? Thanks in advance. Second image.
SELECT
StaffTable.TeacherType,
StaffTable.StaffID,
TeacherQualificationsTable.YearOfGraduation,
TeacherQualificationsTable.SubjectMajorsCombination,
STUFF((SELECT
', ' + [DegreeObtained]
FROM
TeacherQualificationsTable FOR XML PATH('')),1,1,'') AS [DegreeObtained]
FROM
StaffTable
INNER JOIN
TeacherQualificationsTable
ON
StaffTable.StaffID = TeacherQualificationsTable.StaffID
INNER JOIN
AppointmentChronologyTable ON StaffTable.StaffID = AppointmentChronologyTable.StaffID
WHERE
(StaffTable.TeacherType = #TeacherType)
AND (StaffTable.StaffStatus = #StaffStatus)
AND DegreeObtained NOT CONTAINS ('B.Ed (Bachelor of Education)' , 'M.Ed (Master of Education)', 'G.D.E (Graduate Diploma in Education)')
ORDER BY
StaffTable.LastName,
StaffTable.FirstName,
StaffTable.MiddleName
I have a staffTable and a staffQualificationsTable (which will have multiple qualification entries for any given staff). Am required to check if some staff have some given qualifications eg 'B.Ed (Bachelor of Education)' , 'M.Ed (Master of Education)', 'G.D.E (Graduate Diploma in Education)' and return all the staff without it so they will be called to tender theirs or laid off. Please, i hope this is clearer.
I have query like below , I tried to filter out duplicate columns by using Group BY
SELECT contacts.rowid AS ROW_PASS,
duty_rota.rowid AS ROW_PASS_ROTA,
duty_rota.duty_type AS DUTY_TYPE
FROM duty_rota,
duty_types,
contacts
WHERE duty_rota.duty_type = duty_types.duty_type
AND duty_rota.duty_officer = contacts.duty_id
AND sname IS NOT NULL
GROUP BY contacts.rowid,
duty_rota.rowid,
duty_rota.duty_type
ORDER BY duty_date
After playing with the query little bit I came to know we can't filter out distinct using group by while using ROWID. So can somebody please help me to write code (in SQL) with a logic that
if (any row is completely identical with another row of the query o/p)
{
then display only one column
}
I will be using the output as gridview's data source in C#, so if not in SQL - can you help me whether somehow in C# I can achieve to display only identical columns?
If you want to filter duplicate rows, you can use this query:
SELECT Max(duty_rota.rowid) AS ROW_PASS_ROTA,
duty_rota.duty_type AS DUTY_TYPE
FROM duty_rota,
duty_types,
contacts
WHERE duty_rota.duty_type = duty_types.duty_type
AND duty_rota.duty_officer = contacts.duty_id
AND sname IS NOT NULL
GROUP BY duty_rota.duty_type
ORDER BY DUTY_TYPE
Here you go: http://sqlfiddle.com/#!2/2a038/2
Take out the ROWID's. Example: If your table has 3 columns (colA, colB, colC) you could find exact row dups this way...
select a.* from
(
select count(*) dupCnt, colA, colB, colC from myTable
group by colA, colB, colC
) a
where dupCnt > 1
First, the ROWID is a unique field for each row, so using this field you will never have duplicates. The only solution here is to not use it. It's data does not hold anything you would want to display anyway.
Simply put, if you want no duplicates, you need the DISTINCT keyword:
SELECT DISTINCT field1,
field2
FROM table1,
table2
WHERE table1.key1 = table2.key1;
This will select all Field1, Field2 combinations from the two tables. Due to the DISTINCT keyword, each line will only be in the result list once. Duplicates will not be in the result list.
SELECT DISTINCT duty_rota.duty_type AS DUTY_TYPE
FROM duty_rota,
duty_types,
contacts
WHERE duty_rota.duty_type = duty_types.duty_type
AND duty_rota.duty_officer = contacts.duty_id
AND sname IS NOT NULL
ORDER BY duty_date
You will only need to GROUP BY if you need further operations on the result set, like counting the duplicates. If all you need is "no duplicates", the DISTINCT keyword is exactly what you are looking for.
Edit:
In case I misread your question and you want to see only those, that are duplicates, you need to group and you need to filter based on the groups criteria. You can do that using the HAVING clause. It's kind of an additional WHERE of the groups criteria:
SELECT FIELD1, FIELD2, COUNT(*)
FROM TABLE1, TABLE2
WHERE TABLE1.KEY1 = TABLE2.KEY1
GROUPB BY FIELD1, FIELD2
HAVING COUNT(*) > 1
I have two Tables - tblExpenses and tblCategories as follows
tblExpenses
ID (PK),
Place,
DateSpent,
CategoryID (FK)
tblCategory
ID (PK),
Name
I tried various LINQ approaches to get all distinct records from the above two tables but not with much success. I tried using UNION and DISTINCT but it didnt work.
The above two tables are defined in my Model section of my project which in turn will create tables in SQLite. I need to retrieve all the distinct records from both the tables to display values in gridview.
Kindly provide me some inputs to accomplish this task. I did some research to find answer to this question but nothing seemed close to what I wanted. Excuse me if I duplicated this question.
Here is the UNION, DISTINCT approaches I tried:
DISTINCT # ==> Gives me Repetitive values
(from exp in db.Table<tblExpenses >()
from cat in db.Table<tblCategory>()
select new { exp.Id, exp.CategoryId, exp.DateSpent, exp.Expense, exp.Place, cat.Name }).Distinct();
UNION # ==> Got an error while using UNION
I think union already does the distict when you join the two tables you can try somethin like
var query=(from c in db.tblExpenses select c).Concat(from c in
db.tblCategory select c).Distinct().ToList();
You will always get DISTINCT records, since you are selecting the tblExpenses.ID too. (Unless there are multiple categories with the same ID. But that of course would be really, really bad design.)
Remember, when making a JOIN in LINQ, both field names and data types should be the same. Is the field tblExpenses.CategoryID a nullable field?
If so, try this JOIN:
db.Table<tblExpenses>()
.Join(db.Table<tblCategory>(),
exp => new { exp.CategoryId },
cat => new { CategoryId = (int?)cat.ID },
(exp, cat) => new {
exp.Id,
exp.CategoryId,
exp.DateSpent,
exp.Expense,
exp.Place,
cat.Name
})
.Select(j => new {
j.Id,
j.CategoryId,
j.DateSpent,
j.Expense,
j.Place,
j.Name
});
You can try this queries:
A SELECT DISTINCT query like this:
SELECT DISTINCT Name FROM tblCategory INNER JOIN tblExpenses ON tblCategory.categoryID = tblExpenses.categoryID;
limits the results to unique values in the output field. The query results are not updateable.
or
A SELECT DISTINCTROW query like this:
SELECT DISTINCTROW Name FROM tblCategory INNER JOIN tblExpenses ON tblCategory.categoryID = tblExpenses.categoryID;<br/><br/>
looks at the entire underlying tables, not just the output fields, to find unique rows.
reference:http://www.fmsinc.com/microsoftaccess/query/distinct_vs_distinctrow/unique_values_records.asp
Take a look at this psuedo schema (please note this is a simplification so please try not to comment too heavily on the "advisability" of the schema itself). Assume Indexes are inplace on the FKs.
TABLE Lookup (
Lookup_ID int not null PK
Name nvarchar(255) not null
)
TABLE Document (
Document_ID int not null PK
Previous_ID null FK REFERENCES Document(Document_ID)
)
TABLE Document_Lookup (
Document_ID int not null FK REFERENCES Document(Document_ID)
Lookup_ID int not null FK REFERENCES Lookup(Lookup_ID)
)
Volumes: Document, 4 Million rows of which 90% have a null Previous_ID field value; Lookup, 6000 rows, Average lookups attached to each document 20 giving Document_Lookup 80 Millions rows.
Now in a .NET Service have structure to represent a Lookup row like this:-
struct Lookup
{
public int ID;
public string Name;
public List<int> DocumentIDs;
}
and that lookup rows are stored in a Dictionary<int, Lookup> where the key is the lookup ID. An important point here is that this dictionary should contain entries where the Lookup is referenced by at least one document, i.e., the list DocumentIDs should have Count > 0.
My task is populate this dictionary efficiently. So the simple approach would be:-
SELECT dl.Lookup_ID, l.Name, dl.Document_ID
FROM Document_Lookup dl
INNER JOIN Lookup l ON l.Lookup_ID = dl.Lookup_ID
INNER JOIN Document d ON d.Document_ID = dl.Lookup_ID
WHERE d.Previous_ID IS NULL
ORDER BY dl.Lookup_ID, dl.Document_ID
This could then be used to populate a the dictionary fairly efficiently.
The Question: Does the underlying rowset delivery (TDS?) perform some optimization? It seems to me that queries that de-normalise data are very common hence the possiblity that field values don't change from one row to the next is high, hence it would make sense to optomise the stream by not sending field values that haven't changed. Does anyone know whether such an optomisation is in place? (Optomisation does not appear to exist).
What more sophisticated query could I use to eliminate the duplication (I'm think specifically of repeating the name value)? I've heard of such a thing a "nested rowset", can that sort of thing be generated? Would it be more performant? How would I access it in .NET?
I would perform two queries; one to populate the Lookup dictionary then a second to populate the ditionary lists. I would then add code to knock out the unused Lookup entires. However imagine I got my predictions wrong and Lookup ended up being 1 Million rows with only a quarter actually referenced by any document?
As long as the names are relatively short in practice, the optimisation may not be necessary.
The easiest optimisation is to split it into two queries, one to get the names, the other to get the Document_ID list. (can be in the other order if it makes it easier to populate your data structures).
Example:
/*First get the name of the Lookup*/
select distinct dl.Lookup_ID, l.Name
FROM Document_Lookup dl
INNER JOIN Lookup l ON l.Lookup_ID = dl.Lookup_ID
INNER JOIN Document d ON d.Document_ID = dl.Lookup_ID
WHERE d.Previous_ID IS NULL
ORDER BY dl.Lookup_ID, dl.Document_ID
/*Now get the list of Document_IDs for each*/
SELECT dl.Lookup_ID, dl.Document_ID
FROM Document_Lookup dl
INNER JOIN Lookup l ON l.Lookup_ID = dl.Lookup_ID
INNER JOIN Document d ON d.Document_ID = dl.Lookup_ID
WHERE d.Previous_ID IS NULL
ORDER BY dl.Lookup_ID, dl.Document_ID
There are also various tricks you could use to massage these into a single table but I suggest these are not worthwile.
The heirarchical rowsets you are thinking of are the MSDASHAPE OLEDB provider. They can do what you are suggesting but would restrict you to using the OLEDB provider for SQL which may not be what you want.
Finally consider careful XML
For example:
select
l.lookup_ID as "#l",
l.name as "#n",
(
select dl.Document_ID as "node()", ' ' as "node()"
from Document_Lookup dl where dl.lookup_ID = l.lookup_ID for xml path(''), type
) as "*"
from Lookup l
where l.lookup_ID in (select dl.lookup_ID from Document_Lookup dl)
for xml path('dl')
returns:
<dl l="1" n="One">1 2 </dl>
<dl l="2" n="Two">2 </dl>
When you're asking about "nested rowsets" are you referring to using the DbDataReader.NextResult() method?
if your query has two "outputs" (two select statements which return a separate resultsets), you can loop through the first using DbDataReader.Next() and when that returns "false" then you can call DbDataReader.NextResult() and then use DbDataReader.Next() again to continue.
var reader = cmd.ExecuteReader();
while(reader.Read()){
// load data
}
if(reader.NextResult()){
while(reader.Read()){
// lookup record from first result
// load data from second result
}
}
I've done this frequently to reduce duplicate data in a similar situation and it works really well:
SELECT * FROM tableA WHERE [condition]
SELECT * FROM tableB WHERE EXISTS (SELECT * FROM tableA WHERE [condition] AND tableB.FK = tableA.PK)
Disclaimer: I haven't tried this with a resultset as large as you're describing.
The downside of this is you'll need a way to map the second resultset to the first, using a hashtable or order list.