How to do subtract column if lot no and item name and percent is same in SQL - sql

I have two View one for issue and other for Receive.
issue View Output
Lot No Operation Item Wt % Fine Wt
2112001 Lot Addition Create 2 Sadak 180.00 91.94 165.49
2112001 Lot Addition Issue 2 Sadak 30.00 91.94 27.58
2112001 Lot Addition Issue 2 Sadak 300.00 99.50 298.50
2201002 Lot Addition Create 3 Hiway 100.00 91.80 91.80
2201002 Lot Addition Issue 3 Hiway 2.00 91.94 1.84
2201003 Lot Addition Create 4 Saran 19.00 91.40 17.37
2201003 Lot Addition Issue 4 Saran 15.00 91.94 13.79
Receive View Output
Lot No Operation Item Wt % Fine Wt
2112001 Lot Addition Receive 2 Sadak 52.00 91.94 47.81
Output View
Lot No Operation Item Wt % Fine Wt
2112001 Lot Addition Create 2 Sadak 158 91.94 145.27
2112001 Lot Addition Issue 2 Sadak 300 99.50 298.50
2201002 Lot Addition Create 3 Hiway 100 91.80 91.80
2201002 Lot Addition Issue 3 Hiway 2 91.94 1.84
2201003 Lot Addition Create 4 Sarangi 19 91.40 17.37
2201003 Lot Addition Issue 4 Sarangi 15 91.94 13.79
if Lot no, Item Name and percent is same from 2 view than issuewt. and receivewt. should be minus for that lot no. Kindly i suggest me select query what I have done is union and subtract. Suggest front end approach will be better or front end vb.net will be better. copy in two different data table and output will be to third data table.

If the columns and data types are the same, then you can use UNION ALL to combine the data from the 2 views.
Then aggregate the combined results.
Query for MS Sql Server :
SELECT
[Lot No]
, MIN([Operation]) AS [Operation]
, [Item]
, SUM([Wt]) AS [Wt]
, [%]
, SUM([Fine Wt]) AS [Fine Wt]
FROM
(
SELECT [Lot No], [Operation], [Item], [Wt], [%], [Fine Wt]
FROM [Issue View Output]
UNION ALL
SELECT [Lot No], [Operation], [Item], -[Wt], [%], -[Fine Wt]
FROM [Receive View Output]
) q
GROUP BY [Lot No], [Item], [%]
ORDER BY [Lot No], [Item], [%];

Related

Duplicate rows because 1 column has multiple distinct values

I'm running a SELECT query to get data across multiple tables in the same server instance. However I've just noticed that the rows pulled on some data get duplicated because the main table I'm pulling from has a few different values in one of the columns. Here's the query:
SELECT DISTINCT BIF030.C_ACCOUNT AS ACCOUNTNUMBER,
BIF003.C_ACCOUNTTYPE AS ACCOUNTTYPECODE,
CON013.C_DESCRIPTION AS ACCOUNTTYPE,
BIF003.C_DIVISION AS ZONE_DIVISONCODE,
CON028.C_DESCRIPTION AS ZONE_DIVISION,
BIF030.C_METER as METERNUMBER,
BIF005.C_METERCUSTOM1 AS REGISTERNUMBER,
CONVERT(DECIMAL(20,2), BIF030.N_CONSUMP) AS CONSUMPTION,
CON007.C_DESCRIPTION AS UNITS,
BIF030.T_READDATE AS READINGDATE,
MONTH(BIF030.T_READDATE) AS READINGMONTH,
DAY(BIF030.T_READDATE) AS READINGDAY,
YEAR(BIF030.T_READDATE) AS READINGYEAR,
BIF030.I_DAYS AS READINGDAYSCOUNT
FROM ADVANCED.BIF030
LEFT JOIN ADVANCED.CON007 ON CON007.C_UNITS=BIF030.C_UNITS
LEFT JOIN ADVANCED.BIF005 ON BIF005.C_METER=BIF030.C_METER
LEFT JOIN ADVANCED.BIF003 ON BIF003.C_ACCOUNT=BIF030.C_ACCOUNT
LEFT JOIN ADVANCED.CON013 ON CON013.C_ACCOUNTTYPE=BIF003.C_ACCOUNTTYPE
LEFT JOIN ADVANCED.CON028 ON CON028.C_DIVISION=BIF003.C_DIVISION
WHERE T_READDATE > '01-01-2014'
ORDER BY ACCOUNTNUMBER, READINGDATE ASC
I know SELECT DISTINCT is frowned upon, but I get even more rows without it. Here's a sample of what the data looks like when pulled:
ACCOUNTNUMBER
ACCOUNTTYPECODE
ACCOUNTTYPE
ZONE_DIVISIONCODE
ZONE_DIVISION
METERNUMBER
REGISTERNUMBER
CONSUMPTION
UNITS
READINGDATE
READINGMONTH
READINGDAY
READINGYEAR
READINGDAYSCOUNT
1234567
SP
ACCOUNT TYPE 1
00
00-NO ZONE
123456789
987654321
3.00
Thousands of Gallons
2014-01-16 00:00:00.00
1
16
2014
30
1234567
MF
ACCOUNT TYPE 2
02
02-GRAVITY
123456789
987654321
3.00
Thousands of Gallons
2014-01-16 00:00:00.00
1
16
2014
30
1234567
SR
ACCOUNT TYPE 3
02
02-GRAVITY
123456789
987654321
3.00
Thousands of Gallons
2014-01-16 00:00:00.00
1
16
2014
30
I also know the column that is messing this up is the "AccountTypeCode" because other accounts that don't have multiple codes associated with the "AccountNumber" only show 1 set of rows. So this one specifically (and probably others) is tripling the amount of rows pulled when it should only pull one for each "ReadingDate".
Also if anyone knows a good way to optimize the query I'd be happy to learn. I know just enough SQL to be dangerous, but not enough to figure this out. Thanks.
Ok. So good news and I want to add this in case it helps anyone else in the future. I found out that since the ACCOUNTTYPECODE and ZONE_DIVISIONCODE were coming from the table BIF003 I needed to add more in the WHERE statement. This is what fixed it for me:
AND BIF030.C_CUSTOMER = BIF003.C_CUSTOMER
Because the C_CUSTOMER column was different (it's a column in the BIF003 and BIF030 tables) which lead to the separate ACCOUNTTYPECODE results I need to check it in the WHERE statement.
Thanks everyone for kick starting my brain on this one.

Trouble pivoting data in DB2

Before this one is marked as duplicate please know I have done my research on Pivoting in DB2 (even though DB2 doesnt have PIVOT) from these links
Pivoting in DB2 on SO and IBM Developers, but I just cant make sense of how to do it with my Data and need some help. I tried to manipulate my string using examples from both of those links and could not get it to work. Im not asking for anyone to write the full code for me, but just give me a point in the right direction on how to change my string to retrieve the desired result. Thank you in advance.
Current String:
SELECT
cfna1 AS "Customer Name", cfrisk AS "Risk Rating", cfrirc AS "Rated By", date(digits(decimal(cfrid7 + 0.090000, 7, 0))) AS "Risk Rated Date",cfuc3n3 AS "Credit Score", date(digits(decimal(cf3ud7 + 0.090000, 7, 0))) AS "CR Date"
FROM cncttp08.jhadat842.cfmast cfmast
WHERE cfcif# IN ('T000714', 'T000713', 'T000716', 'T000715')
ORDER BY
CASE cfcif#
WHEN 'T000714' THEN 1
WHEN 'T000713' THEN 2
WHEN 'T000716' THEN 3
WHEN 'T000715' THEN 4
END
Result as expected from String:
Customer Name | Risk Rating | Rated By | Risk Rated Date | Credit Score | CR Date
Elmer Fudd 8 MLA 2018-02-08 777 2018-02-08
Result I would like to achieve:
Elmer Fudd
Risk Rating 8
Rated By MLA
Risk Rated Date 2018-02-08
Credit Score 777
CR Date 2018-02-08
Use unpivot method suggested in developers link and use cast to convert all columns to varchar.
Example:
select st1.id1, unpivot1.col1, unpivot1.val1
from (
select id1, char1 , date1, number1
from sometable
) st1,
lateral (values
('char col', cast(st1.char1 as varchar(100))),
('date col', cast(st1.date1 as varchar(100))),
('number col', cast(st1.number1 as varchar(100)))
) as unpivot1 (col1, val1)
order by st1.id1
I don't think that output is possible in sql -- do you mean something like this?
id_group Data_Type Value
1 Name Elmer Fudd
1 Risk Rating 8
1 Rated By MLA
1 Risk Rated Date 2018-02-08
1 Credit Score 777
1 CR Date 2018-02-08
To do this we need another column that brings all the elements together -- I called it "id_group" this is the column that identifys the group

access sql changing where parameters

I have a problem with a DB I'm working on, I suspect is actually a very simple problem, still I can't solve it.
For sake of brevity I will use a very simplified case.
Let's say you have a table were have been stored data about expenses made by different persons, something like this:
IDPerson Expense data
1 2.00 1/1/14
1 1.00 1/2/14
1 1.00 1/3/14
2 1.00 1/1/14
2 1.00 1/2/14
3 1.00 1/3/14
What i need is a query that gives me, for each IDPerson, the totale of expenses made before or on 1/2/14 AND the total of the expenses unregarding the date, so
IDPerson TotalExpense ExpenseBefore1/2/14
1 4.00 2.00
2 2.00 2.00
3 1.00 0.00
It seems to me that to get this you shuld have different where clauses for each column(hence the title)
What I tried:
I tried to use two queries, one without where clause and one with
Where data<=1/2/14
then I used UNION to get the final result, technically it worked, but since this it is not really handy expecially because the real project is much more complicated than this and the final table has much more fields; is there any other way to obtain this?
P.S. You may have noticed that English is not my mothertongue, sorry for any error
SELECT y.IDPerson,y.ExpensesTotal,isnull(x.ExpensesBefore_1_2_2014,0) as ExpensesBefore_1_2_2014 from
(SELECT IDPerson ,sum(expenses) as ExpensesTotal from tableA GROUP BY IDPerson) as y full join ( SELECT tableA.IDPerson , sum(expenses) as ExpensesBefore_1_2_2014 from tableA
where data < '01.02.2014'
GROUP BY tableA.IDPerson ) as x on x.IDPerson = y.IDPerson
This query should work, also it should be preaty quick if the IDPerson is Indexed or PK.
I've updated the query, try this one.
SQL Fiddle : http://sqlfiddle.com/#!3/fdaf0/1

Multiple records in subquery error

I am using MS Access 2010.
I am trying to create a table with three columns by joining different sections of the same table
the dataset is
ID Date Job Title Count of ID
-- --------- ------------------------------------------------------ -----------
1 13-May-14 Security Guards 15
2 13-May-14 Interpreters and Translators 22
3 13-May-14 Laborers and Freight, Stock, and Material Movers, Hand 1
4 13-May-14 Maintenance and Repair Workers, General 23
5 13-May-14 Protective Service Workers, All Other 54
6 13-May-14 Logisticians 65
7 02-Apr-14 Security Guards 88
8 02-Apr-14 Interpreters and Translators 22
9 02-Apr-14 Laborers and Freight, Stock, and Material Movers, Hand 44
10 02-Apr-14 Maintenance and Repair Workers, General 77
11 02-Apr-14 Protective Service Workers, All Other 66
12 02-Apr-14 Logisticians 8
and the query is
SELECT ctrjob.[Job Title], ctrjob.[Count of ID],
(Select ctrjob.[Count of ID] from ctrjob
where ctrjob.[Job Title] = ctrjob.[Job Title] and ctrjob.[Date] = #4/2/2014#)
FROM ctrjob where [ctrjob].[Date] = #5/13/2014# ;
I want my finished table to create a table that places the number of contractors in each job title on 5/13/2014 next to the number from 4/2/2014. The goal is to do a comparison of the change in the number of workers.
But I keep getting an error message that
At most one record can be returned by the subquery
But all I want is for it to return the one corresponding record from the other date. Each time it is executed it should only return the number in job category X on 4/2/2014.
I don't want to use a transform/crosstab because the full dataset has too many dates and I want to use a form to toggle dates in the end. The list of job titles is identical across all dates. I am using MS Access 2010.
Instead of a subquery, use a join:
SELECT a.[Job Title], a.[Count of ID], b.[Count of ID]
FROM ctrjob a INNER JOIN
ctrjob b ON a.[Job Title] = b.[Job Title]
WHERE a.Date = #4/2/2014# AND
b.Date = #5/13/2014#

Optimal solution for interview question

Recently in a job interview, I was given the following problem.
Say I have the following table
widget_Name | widget_Costs | In_Stock
---------------------------------------------------------
a | 15.00 | 1
b | 30.00 | 1
c | 20.00 | 1
d | 25.00 | 1
where widget_name is holds the name of the widget, widget_costs is the price of a widget, and in stock is a constant of 1.
Now for my business insurance I have a certain deductible. I am looking to find a sql statement that will tell me every widget and it's price exceeds the deductible. So if my dedudctible is $50.00 the above would just return
widget_Name | widget_Costs | In_Stock
---------------------------------------------------------
a | 15.00 | 1
d | 25.00 | 1
Since widgets b and c where used to meet the deductible
The closest I could get is the following
SELECT
*
FROM (
SELECT
widget_name,
widget_price
FROM interview.tbl_widgets
minus
SELECT widget_name,widget_price
FROM (
SELECT
widget_name,
widget_price,
50 - sum(widget_price) over (ORDER BY widget_price ROWS between unbounded preceding and current row) as running_total
FROM interview.tbl_widgets
)
where running_total >= 0
)
;
Which gives me
widget_Name | widget_Costs | In_Stock
---------------------------------------------------------
c | 20.00 | 1
d | 25.00 | 1
because it uses a and b to meet the majority of the deductible
I was hoping someone might be able to show me the correct answer
EDIT: I understood the interview question to be asking this. Given a table of widgets and their prices and given a dollar amount, substract as many of the widgets you can up to the dollar amount and return those widgets and their prices that remain
I'll put an answer up, just in case it's easier than it looks, but if the idea is just to return any widget that costs more than the deductible then you'd do something like this:
Select
Widget_Name, Widget_Cost, In_Stock
From
Widgets
Where
Widget_Cost > 50 -- SubSelect for variable deductibles?
For your sample data my query returns no rows.
I believe I understand your question, but I'm not 100%. Here is what I'm assuming you mean:
Your deductible is say, $50. To meet the deductible you have you "use" two items. (Is this always two? How high can it go? Can it be just one? What if they don't total exactly $50, there is a lot of missing information). You then want to return the widgets that aren't being used towards deductible. I have the following.
CREATE TABLE #test
(
widget_name char(1),
widget_cost money
)
INSERT INTO #test (widget_name, widget_cost)
SELECT 'a', 15.00 UNION ALL
SELECT 'b', 30.00 UNION ALL
SELECT 'c', 20.00 UNION ALL
SELECT 'd', 25.00
SELECT * FROM #test t1
WHERE t1.widget_name NOT IN (
SELECT t1.widget_name FROM #test t1
CROSS JOIN #test t2
WHERE t1.widget_cost + t2.widget_cost = 50 AND t1.widget_name != t2.widget_name)
Which returns
widget_name widget_cost
----------- ---------------------
a 15.00
d 25.00
This looks like a Bin Packing problem these are really hard to solve especially with SQL.
If you search on SO for Bin Packing + SQL, you'll find how to find Sum(field) in condition ie “select * from table where sum(field) < 150” Which is basically the same problem except you want to add a NOT IN to it.
I couldn't get the accepted answer by brianegge to work but what he wrote about it in general was interesting
..the problem you
describe of wanting the selection of
users which would most closely fit
into a given size, is a bin packing
problem. This is an NP-Hard problem,
and won't be easily solved with ANSI
SQL. However, the above seems to
return the right result, but in fact
it simply starts with the smallest
item, and continues to add items until
the bin is full.
A general, more effective bin packing
algorithm would is to start with the
largest item and continue to add
smaller ones as they fit. This
algorithm would select users 5 and 4.
So with this advice you could write a cursor to loop over the table to do just this (it just wouldn't be pretty).
Aaron Alton gives a nice link to a series of articles that attempts to solve the Bin Packing problem with sql but basically concludes that its probably best to use a cursor to do it.