Select one table column with distinct record with other table all data - sql

I have 2 table 'userfoodcategory' and 'MenuMaster'.
'userfoodcategory' has the foodcategory and 'MenuMaster' has multiple items along with this category with a column 'isnonveg'.
I want to query 'userfoodcategory' table data with 1 addition column 'isnonveg', this column is in 'MenuMaster' table.
I am trying below query but it is giving redundant record
SELECT DISTINCT ufc.*, MM.isnonveg
FROM MenuMaster MM
LEFT JOIN userfoodcategory ufc ON MM.categoryid = ufc.foodcategoryid
WHERE ufc.USERID = 19 --and MM.isnonveg IS NULL
order by ufc.foodcategoryid
For more details please have a look on below screen shots.
Also I want this as a linq query, but first I was trying to build it in sql and after that I need to convert it in linq as I am new in linq.
Thanks in advance.

You can try to use below Query:
SELECT DISTINCT ufc.*, MM.isnonveg
FROM (select distinct categoryid,isnonveg FROM MenuMaster) MM
LEFT JOIN userfoodcategory ufc ON MM.categoryid = ufc.foodcategoryid
WHERE ufc.USERID = 19 --and MM.isnonveg IS NULL
order by ufc.foodcategoryid

Related

Want to concatenate column of the second query to the first query but getting errors such as "query block has incorrect number of result columns"

SELECT
ID, PRIM_EMAIL, SEC_EMAIL, PHONE
FROM
STUDENTS.RECORDS
WHERE
ID IN (SELECT ID FROM STUDENTS.INFO WHERE ROLL_NO = '554')
UNION
SELECT NAME
FROM STUDENTS.INFO
WHERE ROLL_NO = '554';
Here Roll_No is a user inserted data so for now I have hard coded it. Basically with the help of ROLL_NO I sort the STUDENTS_INFO table from where I get the ID and based on that I try to get PRIM_EMAIL, SEC_EMAIL, PHONE from the STUDENTS.RECORDS table while matching the foreign keys of both the tables. In addition to the current result set I also want to have the prov_name column.
Any help is very much appreciated. Thank you!
I suspect that you want to put all this information on the same row, which suggests a join rather than union all:
select
r.ID,
r.PRIM_EMAIL,
r.SEC_EMAIL,
r.PHONE,
r.NAME
from STUDENTS.RECORDS r
inner join STUDENTS.INFO i ON i.ID = r.ID
where I.ROLL_NO = '554';
I think the source of your error query block has incorrect number of result columns is coming from trying to union together a table with 4 columns (id, prim_email, sec_email, phone) with 1 column (name).
From your question, I am gathering that you want a single table of id, prim_email, sec_email, phone from students.records and name from students.info.
I think the following query using CTE's might get you (partially) to your final result. You may want to refactor for optimizing performance.
with s_records as ( select * from students.records ),
s_info as ( select * from students.info ),
joined as (
select
s_records.id,
s_records.prim_email,
s_records.sec_email,
s_records.phone,
s_info.name
from s_records
left join s_info
on s_records.roll_no = s_info.roll_no
where roll_np = '554' )
select * from joined
Overall, I think that a join will be part of your solution rather than a union :-)

SQL Server ISNULL multiple columns

I have the following query which works great but how do I add multiple columns in its select statement? Following is the query:
SELECT ISNULL(
(SELECT DISTINCT a.DatasourceID
FROM [Table1] a
WHERE a.DatasourceID = 5 AND a.AgencyID = 4 AND a.AccountingMonth = 201907), NULL) TEST
So currently I only get one column (TEST) but would like to add other columns such as DataSourceID, AgencyID and AccountingMonth.
If you want to output a row for some condition (or requested values ) and output a row when it does not meet condition,
you can set a pseudo table for your requested values in the FROM clause and make a left outer join with your Table1.
SELECT ISNULL(Table1.DatasourceId, 999999),
Table1.AgencyId,
Table1.AccountingMonth,
COUNT(*) as count
FROM ( VALUES (5, 4, 201907 ),
(6, 4, 201907 ))
AS requested(DatasourceId, AgencyId, AccountingMonth)
LEFT OUTER JOIN Table1 ON requested.agencyid=Table1.AgencyId
AND requested.datasourceid = Table1.DatasourceId
AND requested.AccountingMonth = Table1.AccountingMonth
GROUP BY Table1.DatasourceId, Table1.AgencyId, Table1.AccountingMonth
Note that:
I have put a ISNULL for the first column like you did to output a particular value (9999) when no value is found.
I did not put the ISNULL(...,NULL) like your query in the other columns since IMHO it is not necessary: if there is no value, a null will be output anyway.
I added a COUNT(*) column to illustrate an aggregate, you could use another (SUM, MIN, MAX) or none if you do not need it.
The set of requested values is provided as a constant table values (see https://learn.microsoft.com/en-us/sql/t-sql/queries/table-value-constructor-transact-sql?view=sql-server-2017)
I have added multiple rows for requested conditions : you can request for multiple datasources, agencies or months in one query with one line for each in the output.
If you want only one row, put only one row in "requested" pseudo table values.
There must be a GROUP BY, even if you do not want to use an aggregate (count, sum or other) in order to have the same behavior as your distinct clause , it restricts the output to single lines for requested values.
To me it seems that you want to see does data exists, i guess that your's AgencyID is foreign key to agency table, DataSourceID also to DataSource, and that you have AccountingMonth table which has all accounting periods:
SELECT ds.ID as DataSourceID , ag.ID as AgencyID , am.ID as AccountingMonth ,
ISNULL(COUNT(a.*),0) as Count
FROM [Table1] a
RIGHT JOIN [Datasource] ds ON ds.ID = a.DataSourceID
RIGHT JOIN [Agency] ag ON ag.ID = a.AgencyID
RIGHT JOIN [AccountingMonth] am on am.ID = a.AccountingMonth
GROUP BY ds.ID, ag.ID, am.ID
In this way you can see count of records per group by criteria. Notice RIGHT join, you must use RIGHT JOIN if you want to include all record from "Right" table.
In yours query you have DISTINCT a.DatasourceID and WHERE a.DatasourceID = 5 and it returns 5 if in table exists rows that match yours WHERE criteria, and returns null if there is no data. If you remove WHERE a.DatasourceID = 5 your query would break with error: subquery returned multiple rows.
the way you are doing only allows for one column and one record and giving it the name of test. It does not look like you really need to test for null. because you are returning null so that does nothing to help you. Remove all the null testing and return a full recordset distinct will also limit your returns to 1 record. When working with a single table you don't need an alias, if there are no spaces or keywords braced identifiers not required. if you need to see if you have an empty record set, test for it in the calling program.
SELECT DatasourceID, AgencyID,AccountingMonth
FROM Table1
WHERE DatasourceID = 5 AND AgencyID = 4 AND AccountingMonth = 201907

MS Access SQL with self join produces less results than original table, what does the set of records that aren't present in query represent?

My original table (File05292019) has 22,904 records. I perform a self join on 3 of the fields as shown below and the result is 22,886. Why is this the case? What do the missing records represent?
SELECT File05292019.LastName, File05292019.FirstName, File05292019.SubscriberSocialSecurityNumber
FROM File05292019
INNER JOIN File05292019 AS File05292019_1
ON (File05292019.SubscriberSocialSecurityNumber = File05292019_1.SubscriberSocialSecurityNumber)
AND (File05292019.LastName = File05292019_1.LastName)
AND (File05292019.FirstName = File05292019_1.FirstName)
GROUP BY File05292019.LastName, File05292019.FirstName, File05292019.SubscriberSocialSecurityNumber;
Because of group operator. You should have duplicate records in result set
Check by running this query
SELECT File05292019.LastName, File05292019.FirstName, File05292019.SubscriberSocialSecurityNumber
FROM File05292019
INNER JOIN File05292019 AS File05292019_1
ON (File05292019.SubscriberSocialSecurityNumber = File05292019_1.SubscriberSocialSecurityNumber)
AND (File05292019.LastName = File05292019_1.LastName)
AND (File05292019.FirstName = File05292019_1.FirstName)
the presence of group by suggest that
this mean that you have some rows with the same values
you could try uisng
SELECT File05292019.LastName
, File05292019.FirstName
, File05292019.SubscriberSocialSecurityNumber
count(*)
FROM File05292019
GROUP BY File05292019.LastName
, File05292019.FirstName
, File05292019.SubscriberSocialSecurityNumber
HAVING count(*) > 1
for find these rows
Couple of possibilities:
NULL values exist in the JOIN fields: SubscriberSocialSecurityNumber, LastName, and FirstName. Because NULL = NULL is a False statement, joins exclude nulls (non-value entities).
Duplicate values in GROUP BY fields where the aggregation returns distinct values by grouping. Add the COUNT(*) As RecordCount aggregate to see which fields have more than 1 value.
Possibly subscribers changed their names but retained same SSNs; names and SSNs were incorrectly inputted; or several records use a default status like 999-99-9999?

SQL Combining two different tables

(P.S. I am still learning SQL and you can consider me a newbie)
I have 2 sample tables as follows:
Table 1
|Profile_ID| |Img_Path|
Table 2
|Profile_ID| |UName| |Default_Title|
My scenario is, from the 2nd table, i need to fetch all the records that contain a certain word, for which i have the following query :
Select Profile_Id,UName from
Table2 Where
Contains(Default_Title, 'Test')
ORDER BY Profile_Id
OFFSET 5 ROWS
FETCH NEXT 20 ROWS ONLY
(Note that i am setting the OFFSET due to requirements.)
Now, the scenario is, as soon as i retrieve 1 record from the 2nd table, i need to fetch the record from the 1st table based on the Profile_Id.
So, i need to return the following 2 results in one single statement :
|Profile_Id| |Img_Path|
|Profile_Id| |UName|
And i need to return the results in side-by-side columns, like :
|Profile_Id| |Img_Path| |UName|
(Note i had to merge 2 Profile_Id columns into one as they both contain same data)
I am still learning SQL and i am learning about Union, Join etc. but i am a bit confused as to which way to go.
You can use join:
select t1.*, t2.UName
from table1 t1 join
(select Profile_Id, UName
from Table2
where Contains(Default_Title, 'Test')
order by Profile_Id
offset 5 rows fetch next 20 rows only
) t2
on t2.profile_id = t1.profile_id
SELECT a.Profile_Id, a.Img_Path, b.UName
FROM table1 a INNER JOIN table2 b ON a.Profile_Id=b.Profile_Id
WHERE b.Default_Title = 'Test'

SQL - Finding duplicates based on 3 columns with different data types

SQL noob here, let me know if I'm not wording anything right. I'm trying to find all entries where there is more than one instance of the same data in 3 columns. Below is some sample data from the 3 columns.
formatid type_from call_desc_code
20 002694W0:USAGE V9
20 013030W0:USAGE OM
20 013030W0:USAGE NULL
From what I understand checksum can be used for this but the output from the below query doesn't seem right. The first part of the query that I'm putting into the #temp table has 29824 results which tells me there should be only 29824 unique combinations of the 3 columns but when I've run the full query then tried removing duplicates in Excel based on only those 3 columns to sanity check the results I have a whole lot more then 29824 entries left.
The formatid is a smallint data type so when I've tried just concatenating the cells with + it returns a conversion failed error. I'm running SQL Server 2012 but I don't think the database is on the same as it doesn't recognise the concat function.
select checksum(formatid,type_from,call_desc_code) & checksum(reverse(formatid),reverse(type_from),reverse(call_desc_code)) as [checksum], count(*) as [Blah]
into #temp
from Table
group by checksum(formatid,type_from,call_desc_code) & checksum(reverse(formatid),reverse(type_from),reverse(call_desc_code))
having count(*) > 1
select * from
Table
where checksum(formatid,type_from,call_desc_code) & checksum(reverse(formatid),reverse(type_from),reverse(call_desc_code)) in (select [checksum] from #temp)
drop table #temp
this will get you everything from your source table which has duplicates
select *
from table t
inner join
(select formatid,type_from,call_desc_code
from Table
group by formatid,type_from,call_desc_code
having count(*) > 1) dup
on dup.formatid = t.formatid
and dup.type_from = t.type_from
and dup.call_desc_code = t.call_desc_code