sql server query how to have multiple column comparision with subquery - sql

How can I make the update query to work based on the sub query?
How can I compare all these columns in the sub query to the columns in the update statement?
Is there some neat and clean way to do it?
The query I am trying with it is shown below:
UPDATE Temp_CropData
SET RecordStatus = 0,
Remarks = ISNULL(Remarks, '') +' Duplicate Records'
WHERE
(SELECT Commodity ,City,Period,CropCondition
FROM [Temp_CropData]
GROUP BY DDate,Commodity,City,Period,CropCondition
HAVING count(*) >1)

Try using MERGE:
MERGE INTO Temp_CropData
USING (
SELECT Commodity, City, Period, CropCondition
FROM Temp_CropData
GROUP
BY DDate, Commodity, City, Period, CropCondition
HAVING COUNT(*) > 1
) AS source
ON Temp_CropData.Commodity = source.Commodity
AND Temp_CropData.City = source.City
AND Temp_CropData.Period = source.Period
AND Temp_CropData.CropCondition = source.CropCondition
WHEN MATCHED THEN
UPDATE
SET RecordStatus = 0,
Remarks = ISNULL(Remarks, '') + ' Duplicate Records';
I'm slightly suspicious of the fact that your subquery's SELECT and GROUP BY clauses do not match, though (i.e. DDate is in the GROUP BY but not the SELECT).

Try this:
UPDATE cd
SET RecordStatus = 0,
Remarks = ISNULL(Remarks, '') +' Duplicate Records'
FROM Temp_CropData cd
JOIN (SELECT Commodity ,City,Period,CropCondition
FROM [Temp_CropData]
GROUP BY DDate,Commodity,City,Period,CropCondition
HAVING count(*) >1) dup
ON cd.DDate = dup.DDate AND cd.Commodity=dup.Commodity AND cd.City = dup.City
AND cd.Period = dup.Period AND cd.CropCondition = dup.CropCondition

Related

How to update a table from a select query

i am creating a temp table using DB facade and then using select query i need to update some columns in temp table based on condition
DB::update('update table_temp_topcustomer
set ordercount = aaa.ordercount
from
(select count(id) as ordercount,mobileno
from order_hdrs
group by mobileno
) as aaa
where table_temp_topcustomer .mobileno = aaa.mobileno
');
it gives this error
Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'from (select count(id) as ordercount,mobileno from order_hdrs group by mobileno ' at line 1 (SQL: update table_temp_topcustomer set ordercount = aaa.ordercount from (select count(id) as ordercount,mobileno from order_hdrs group by mobileno ) as aaa )
How can i achieve this?
UPDATE table_temp_topcustomer JOIN
( SELECT order_hdrs count(*) as ordercount
FROM order_hdrs
GROUP BY mobileno
) AS aaa
ON table_temp_topcustomer.mobileno = aaa.mobileno
SET table_temp_topcustomer.ordercount = aaa.ordercount
I guess you can't do in single query. As per my understanding. First get the select result and in loop do update.
You should try something like below.
$result = DB::select('select count(id) as ordercount,mobileno
from order_hdrs
group by mobileno');
foreach($result as $item) {
DB::update('update table_temp_topcustomer
set ordercount = '. $item->ordercount .'
where table_temp_topcustomer.mobileno = ' $item->mobileno);
}

Union ALL not giving the column\ names for second group

I am using the tool SQLDBx. which i highly like btw. I have 5 groups of series of Select statements and then I made a UNION ALL after the first group. Now it does run correctly
and displays the output but it does not assign the second group'
s field names.
For example. I am greatly abridging
Completed the SQL's needed to mimic a IBM i display screen. There are 5 product groups making up the screen. I was hoping to have one large Command SQL having the 5 SQLs using UNION ALL. This does 'compile' as a Command. However, it does only brings in the first part fields not the second. So this field is not included in the list of fields tree for COMMAND. PROGR2R2PST,
Is there something not correct how doing the UNION ALL? OUTPUT assigns the column name
of the first group to the second group.
HLDGR1PUN
21454
87273
so if i wanted to have one large SQL with union ALLs, it wont work. is there something other than UNION ALL I should use?
SELECT
count(*) as PROGR1PST,
(
SELECT COALESCE(SUM(OdQty#),0)
FROM ASTCCDTA.OEORH48,ASTCCDTA.TRNSTAT2,ASTDTA.OEORD1
WHERE OHCOM# = TSCOM# AND OHORD# = TSORD# AND OHCOM# = ODCOM# AND OHORD# = ODORD#
AND TSSTAT IN('AEP','BGE')
AND OHORDT IN('RTR','INT','SAM')
AND OHREQD < replace(char(current date, iso), '-', '')
AND OHHLDC = ' '
AND ODPRLC = 'ENG'
AND substr(odprt#,1,5) <> 'NOENG' AND OHORD# in(SELECT a.TSORD# FROM ASTCCDTA.TRNSTAT2 a
WHERE a.tsstat IN('AEP','BGE','EAS','REL','STP'))
) AS PROGR1PUN,
(
SELECT count(*)
FROM ASTCCDTA.OEORH48,ASTCCDTA.TRNSTAT2,ASTCCDTA.OETRA99
WHERE OHCOM# = TSCOM# AND OHORD# = TSORD#
AND (otCOM# = OHCOM# AND OTORD#= OHORD# AND ottrnc = 'AQC')
AND TSSTAT IN('AEP','BGE')
AND OHORDT IN('RTR','INT','SAM')
AND OHREQD = replace(char(current date, iso), '-', '') AND OHHLDC = ' ' AND OHORD# in(SELECT a.TSORD# FROM ASTCCDTA.TRNSTAT2 a
WHERE a.tsstat IN('AEP','BGE','EAS','REL','STP'))
) AS PROGR1TOD,
(
etc..
UNION ALL
SELECT
count(*) as PROGR2R2PST,
(SELECT COALESCE(SUM(OdQty#),0) FROM ASTCCDTA.OEORH48,ASTCCDTA.TRNSTAT2,ASTDTA.OEORD1
WHERE OHCOM# = TSCOM# AND OHORD# = TSORD# AND OHCOM# = ODCOM# AND OHORD# = ODORD#
AND TSSTAT IN('AEP','BGE')
AND OHORDT IN('CUS','CIN','SMC','COC','DON')
AND OHREQD < replace(char(current date, iso), '-', '')
AND OHHLDC = ' '
AND ODPRLC = 'ENG'
AND substr(odprt#,1,5) <> 'NOENG' AND OHORD# in(SELECT a.TSORD# FROM ASTCCDTA.TRNSTAT2 a
WHERE a.tsstat IN('AEP','BGE','EAS','REL','STP'))
) AS PROGR2PUN,
I don't think you can get the result you want by "nesting" the SQL statements and joining them with UNION.
This structure may work, depending upon your requirements:
SELECT 'Name1' AS Label , COUNT(*) AS The_Count
FROM table1
WHERE ...
UNION ALL
SELECT 'PROGR2R2PST', COUNT(*)
FROM table2
WHERE ...
UNION ALL
SELECT 'Name3', COUNT(*)
FROM table3
WHERE ...
This will give you back one row per select:
Label The_Count
--------------------
Name1 45867
PROGR2R2PST 22
Name3 1234
Note that the column names come from the first select. If this format doesn't match your requirements, please be more explicit in the question or in comments and I will try to help.

SQL group by issue when i try to get some info

I can not figure it out:
I have a table called ImportantaRecords with fields like market, zip5, MHI, MHV, TheTable and I want to group all the records by zip5 that have TheTable = 'mg'… I tried this :
select a.Market,a.zip5,count(a.zip5),a.MHI,a.MHV,a.TheTable from
(select * from ImportantaRecords where TheTable = 'mg') a
group by a.Zip5
but it gives me the classic error with not an aggrefate function
and then I tried this:
select Market,zip5,count(zip5),MHI,MHV,TheTable from ImportantaRecords where TheTable = 'mg'
group by Zip5
and the same thing…
any help ?
You did not state what database you are using but if you are getting an error about columns not being in an aggregate function, then you might need to add the columns not in an aggregate function to the GROUP BY:
select Market,
zip5,
count(zip5),
MHI,
MHV,
TheTable
from ImportantaRecords
where TheTable = 'mg'
group by Market, Zip5, MHI, MHV, TheTable;
If grouping by the additional columns alters the result that you are expecting, then you could use a subquery to get the result:
select i1.Market,
i1.zip5,
i2.Total,
i1.MHI,
i1.MHV,
i1.TheTable
from ImportantaRecords i1
inner join
(
select zip5, count(*) Total
from ImportantaRecords
where TheTable = 'mg'
group by zip5
) i2
on i1.zip5 = i2.zip5
where i1.TheTable = 'mg'

SQL Query takes to long to return data

Looking for a better way to write this query and my SQL skills aren't great, basic really so looking for any pointers to make this better. This is only the first two columns and the full report will have a further 10.
I'm taking a specific set of repair types and doing analysis on them with counts and calculations. The 1st is jobs brought forward to the current financial year and the second is total amount of jobs currently received.
SELECT
"Type",
(
SELECT
NVL (COUNT(jjo.jjobno), 0)
FROM
jjobh jjo
WHERE
jjo.jclcode = 'L'
AND jjo.jstatus <> '6'
AND jjo.year_rec <> (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
AND (
week_comp IS NULL
OR year_comp = (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
)
AND jjo.jrepair_type = "Type"
) AS "B/F",
(
SELECT
NVL (COUNT(jjo.jjobno), 0)
FROM
jjobh jjo
WHERE
jjo.jclcode = 'L'
AND jjo.jstatus <> '6'
AND jjo.year_rec = (
SELECT
sub_code
FROM
code_table
WHERE
main_code = 'YEAR'
)
AND jjo.jrepair_type = "Type"
) AS "Recvd"
FROM
(
SELECT
rep.repair_type_code AS "Type"
FROM
repair_type rep
WHERE
rep.client = 'L'
AND rep.work_centre = '004682'
ORDER BY
rep.repair_type_code
)
ORDER BY
"Type";
Your code is a mess. I suspect you want something like:
SELECT jjo.jrepair_type, count(*) as valbf
FROM (SELECT coalesce(COUNT(jjo.jjobno), 0)
FROM jjobh jjo cross join
(SELECT sub_code
FROM code_table
WHERE main_code = 'YEAR'
) sc
WHERE jjo.jclcode = 'L' AND
jjo.jstatus <> '6' AND
jjo.year_rec <> sc.sub_code AND
(week_comp IS NULL OR
year_comp = sc.sub_code
)
) jjo join
(SELECT rep.repair_type_code AS "Type"
FROM repair_type rep
WHERE rep.client = 'L' AND
rep.work_centre = '004682'
) rtc
on jjo.jrepair_type = rtc.repair_type_code
group by jjo.jrepair_type;
It looks like you want to join the "jjo" table to the "repair type code" table, producing information about each repair type. The order by in the subquery is useless.
My suggestion is to move the "jjo" table to the outer "from". You should also move the WHERE clauses to the outermost WHERE clause (which I didn't do). I haven't quite figured out the date logic, but this might get you on the right track.

SQL Server MERGE, if exist then update else insert

I've a table called data with columns ip, report_date, group, value. The primary key is ip, report_date and group together.
When the table is empty and I run the statement below there is nothing inserted. What's wrong with my statement?
When there is a match the record is updates according plan...
MERGE bc_data2 AS Target
USING (SELECT ip, report_date, group, value FROM bc_data2 As b
WHERE b.ip = '1.1.1.2'
AND b.report_date = '2/29/2012'
AND b.group = 'EPO-Client-Update') AS Source
ON (Target.ip = Source.ip
AND Target.frequency = Source.frequency
AND Target.report_date = Source.report_date
AND Target.service = Source.service
AND Target.proxy_service = Source.proxy_service
AND Target.proxy = Source.proxy
AND Target.service_group = Source.service_group)
WHEN MATCHED THEN
UPDATE SET Target.value = Target.value + 1
WHEN NOT MATCHED BY Target THEN
INSERT (ip, report_date, group, value)
VALUES ('1.1.1.2', '2/29/2012', 'EPO-Client-Update', 119437142);
You don't add any rows because your using clause is not returning any rows. Put your constants in the using clause with column aliases and use the fields in the when not matched
Something like this with a couple of fields removed simplicity.
merge bc_data2 as T
using (select '1.1.1.2' as ip,
'2012-02-29' as report_date,
1194370142 as value) as S
on T.ip = S.ip and
T.report_date = S.report_date
when matched then
update set T.value = T.value + 1
when not matched then
insert (ip, report_date, value)
values(ip, report_date, value);
I've found that NULLs don't compare well in the ON clause of the MERGE statement. However, converting NULLs to blanks is a valid workaround. I would modify the the ON statement to look something like this.
ON (ISNULL(Target.ip, '') = ISNULL(Source.ip, '')
AND ISNULL(Target.frequency, '') = ISNULL(Source.frequency, '')
AND ISNULL(Target.report_date, '') = ISNULL(Source.report_date, '')
AND ...)