SQL Server Loop Over Records - sql

I have a view vwDocumentLinks with data as shown below:
I have another table RiskTypes with data as below.
The link between the table & viewis : Idx25 = Risk Type and LinkDocNo = DocumentType. What I am trying to achieve is to get DocumentType in RiskTypes that's not in the view vwDocumentLinks foreach BaseValue and where Idx25 = RiskType. An example using a single BaseValue will be:
SELECT * FROM RiskTypeDocuments WHERE RiskType = 'BUSINESS LIMITED COMPANY' AND DocumentType NOT IN (SELECT LINKDOCNO FROM DBO.VWLINKS WHERE BaseValue = '00007573-1637-4B8E-9374-730AF58BCFB6')
I tried the below query and it's not working as expected. Any help will be greatly appreciated. I am a newbie in SQL
SELECT dbo.RiskTypeDocuments.DocumentType,
dbo.RiskTypeDocuments.RiskType,
dbo.vwLinks.BaseValue AS Document
FROM dbo.vwLinks LEFT OUTER JOIN
dbo.RiskTypeDocuments ON dbo.vwLinks.LinkDocNo =
dbo.RiskTypeDocuments.DocumentType AND dbo.vwLinks.Idx25 =
dbo.RiskTypeDocuments.RiskType
WHERE dbo.RiskTypeDocuments.DocumentType IS NOT NULL
ORDER BY Document
NB: I can't change the schema. I can only create views from the existing tables.
Sample Data from the two datasets: vwDocumentLinks & RiskTypeDocuments

SELECT a.DocumentType,
a.RiskType,
b.BaseValue AS Document
FROM dbo.RiskTypeDocuments as a
INNER JOIN (Select distinct Idx25, BaseValue from vwDocumentLinks) as b on b.Idx25 = a.RiskType
where a.DocumentType not in (Select LINKDOCNO from vwDocumentLinks as c where c.basevalue = b.BaseValue )

I think what you are looking for is NOT EXISTS. It takes a little to get your head around, but the idea is to have what is called a correlated subquery. The subquery is joined to the main query, hence the term correlated.
SELECT *
FROM RiskTypeDocuments
WHERE NOT EXISTS (
SELECT 1 FROM vwDocumentLinks
WHERE RiskTypeDocuments.RiskType = vwDocumentLinks.idx25
AND RiskTypeDocuments.DocumentType = vwDocumentLinks.LinkDocNo
)

If you want to retrieve the records which don't exist in the view then
Try like this
SELECT d.DocumentType,
d.RiskType,
v.BaseValue
FROM dbo.vwLinks AS v
OUTER JOIN dbo.RiskTypeDocuments d ON v.LinkDocNo = d.DocumentType AND v.vwLinks.Idx25 =d.RiskType
WHERE v.BaseValue IS NULL
ORDER BY DocumentType

Related

Display only result > 2

I face a problem with the result on my script.
My formula for MARGIN is ((plnamt-(ibhexc/ibhand))/plnamt)*100.
I want to display only result > 2. How to do this? Please help.
This my script:
select
a.plnitm,a.plnstr,max(a.plncdt),max(a.plnndt),max(a.plnamt),max(a.plnevt),b.idept,c.ibhand,c.ibhexc,
decimal((c.ibhexc/c.ibhand),12,4) as AVG_COST,
decimal(((((max(a.plnamt)-(c.ibhexc/c.ibhand))/(max(a.plnamt))))*100),12,4) as MARGIN
from prcpln a
inner join invmst b on a.plnitm = b.inumbr
inner join invbal c on a.plnitm = c.inumbr and a.plnstr = c.istore and c.ibhand <> 0
where a.plnstr = ''14006''
group by a.plnitm,a.plnstr,b.idept,c.ibhand,c.ibhexc
order by a.plnitm
Simplistically, for situations like this, you can take your query and put it inside a cte:
WITH q AS (
select
a.plnitm,a.plnstr,max(a.plncdt),max(a.plnndt),max(a.plnamt),max(a.plnevt),b.idept,c.ibhand,c.ibhexc,
decimal((c.ibhexc/c.ibhand),12,4) as AVG_COST,
decimal(((((max(a.plnamt)-(c.ibhexc/c.ibhand))/(max(a.plnamt))))*100),12,4) as MARGIN
from prcpln a
inner join invmst b on a.plnitm = b.inumbr
inner join invbal c on a.plnitm = c.inumbr and a.plnstr = c.istore and c.ibhand <> 0
where a.plnstr = ''14006''
group by a.plnitm,a.plnstr,b.idept,c.ibhand,c.ibhexc
)
SELECT * FROM q WHERE margin > 2
ORDER BY q.plnitm
This is similar to the advice to use HAVING - a HAVING is a "where clause that is done after a GROUP BY"
A cte is a way of taking some calculated block of data and giving it an alias that can be used just like a table. I wanted to answer this way to point out to you that queries don't have to be formed purely from tables; tables are just blocks of data (with a name), and the output from a select is also "just a block of data" that can be given a name (by use of a cte or subquery) and then used just like a table is

Duplicate rows while multiplying two columns of two different tables using joins

I have these following tables
Question_Segment_Master
Question_Set_Details
While I am joining these two tables I am getting duplicate rows..
Please view fiddle,where I posted those twos schema and it's data..
http://sqlfiddle.com/#!18/4c84f/10
This is my expected OP
You need to get the question_marks of each segment. Also, you should JOIN using the branch_id, test_id, subject_code_id along with the segment_id.
Using JOIN and then take Distinct values
SELECT DISTINCT qsm.segment_id, segment_name, segment_description
, must_attend_question AS tot_attented_question, total_question AS tot_questions
, (qsd.question_marks * must_attend_question) AS tot_marks
, '' AS marks_obtain
FROM dbo.Question_Segment_Master AS qsm
INNER JOIN dbo.Question_Set_Details AS qsd
ON (qsd.branch_id = qsm.branch_id AND qsd.test_id = qsm.test_id
AND qsd.segment_id = qsm.segment_id AND qsd.subject_code_id = qsm.subject_code_id)
WHERE qsm.subject_code_id = 1 and qsm.test_id = 1 and qsm.branch_id = 15;
Demo
You were missing the segment_id in your join clause
SELECT DISTINCT
qsm.segment_id,
qsm.segment_name,
qsm.segment_description,
qsm.must_attend_question tot_attented_question,
qsm.total_question tot_questions,
(qsd.question_marks * must_attend_question) tot_marks,
'' AS marks_obtain
FROM dbo.question_segment_master qsm
INNER JOIN dbo.question_set_details qsd on
qsd.test_id = qsm.test_id
and qsd.segment_id = qsm.segment_id
WHERE qsm.test_id=1
AND qsm.branch_id = 15
AND qsm.subject_code_id =1 AND qsd.question_set_id = 1

Comparing Query Result With Table and Retrieve Specific Field

My Query
SELECT
stoMast.sStockistCode,
stoMast.sStateName,
stoMast.sDivision,
stateMap.sRMCode
FROM
tblRSM_State_Mapping stateMap
INNER JOIN
tblStockistMaster stoMast ON
stateMap.sStateName = stoMast.sStateName
WHERE
stateMap.sRMCode = 'MCNE04001'
and
stoMast.sDivision = 'CIDIS'
except
select
sStockistCode,
sStateName,
sDivision,
sRMCode
From
tblEntry
Again I would like to compare the query result columns
sStockistCode
sStateName
sDivision
with tblStockistMaster with the same fields
sStockistCode
sStateName
sDivision
and retrieve the STOCKIST NAME.
Don't know how to compare the above query result with the table.
Maybe you can use following SQL code used with CTE expression
;with cte as (
SELECT
stoMast.sStockistCode,
stoMast.sStateName,
stoMast.sDivision,
stateMap.sRMCode
FROM
tblRSM_State_Mapping stateMap
INNER JOIN
tblStockistMaster stoMast ON
stateMap.sStateName = stoMast.sStateName
WHERE
stateMap.sRMCode = 'MCNE04001'
and
stoMast.sDivision = 'CIDIS'
except
select
sStockistCode,
sStateName,
sDivision,
sRMCode
From
tblEntry
)
select
cte.*,
sm.sStockistName
from cte
left join tblStockistMaster as sm
on sm.sStockistCode = cte.sStockistCode and
sm.sStateName = cte.sStateName and
sm.sDivision = cte.sDivision
-- I retrieve the stockist Name
SELECT
stoMast.sStockistName,
FROM
tblRSM_State_Mapping stateMap
INNER JOIN
tblStockistMaster stoMast
ON stateMap.sStateName = stoMast.sStateName
-- I'm joining table entry If I can match
LEFT JOIN
tblEntry tbl
on tbl.sStockistCode = stoMast.sStockistName
AND tbl.sStateName = stoMast.sStateName
AND tbl.sDivision = stoMast.sDivision
AND tbl.sRMCode = stateMap.sRMCode
WHERE
stateMap.sRMCode = 'MCNE04001'
and stoMast.sDivision = 'CIDIS'
-- And The the exept thing, I don't want that got a match with the tableentry
AND COALESCE(tbl.sStockistCode, tbl.sStateName, tbl.sDivision, tbl.sRMCode) is null
I expect it is what you wanted to get. On another way please help us understand wht you come from (tables and idea of what data can be in) and the result you want. Will be easier to create a query.

Confused in join query in SQL

The following works:
SELECT IBAD.TRM_CODE, IBAD.IPABD_CUR_QTY, BM.BOQ_ITEM_NO,
IBAD.BCI_CODE, BCI.BOQ_CODE
FROM IPA_BOQ_ABSTRCT_DTL IBAD,
BOQ_CONFIG_INF BCI,BOQ_MST BM
WHERE BM.BOQ_CODE = BCI.BOQ_CODE
AND BCI.BCI_CODE = IBAD.BCI_CODE
AND BCI.STATUS = 'Y'
AND BM.STATUS = 'Y'
order by boq_item_no;
Results:
But after joining many tables with that query, the result is confusing:
SELECT (SELECT CMN_NAME
FROM CMN_MST
WHERE CMN_CODE= BRI.CMN_RLTY_MTRL) MTRL,
RRI.RRI_RLTY_RATE AS RATE,
I.BOQ_ITEM_NO,
(TRIM(TO_CHAR(IBAD.IPABD_CUR_QTY,
'9999999999999999999999999999990.999'))) AS IPABD_CUR_QTY,
TRIM(TO_CHAR(BRI.BRI_WT_FACTOR,
'9999999999999999999999999999990.999')) AS WT,
TRIM(TO_CHAR((IBAD.IPABD_CUR_QTY*BRI.BRI_WT_FACTOR),
'9999999999999999999999990.999')) AS RLTY_QTY,
(TRIM(TO_CHAR((IBAD.IPABD_CUR_QTY*BRI.BRI_WT_FACTOR*RRI.RRI_RLTY_RATE),
'9999999999999999999999990.99'))) AS TOT_AMT,
I.TRM_CODE AS TRM
FROM
(SELECT * FROM ipa_boq_abstrct_dtl) IBAD
INNER JOIN
(SELECT * FROM BOQ_RLTY_INF) BRI
ON IBAD.BCI_CODE = BRI.BCI_CODE
INNER JOIN
(SELECT * FROM RLTY_RATE_INF) RRI
ON BRI.CMN_RLTY_MTRL = RRI.CMN_RLTY_MTRL
INNER JOIN
( SELECT IBAD.TRM_CODE, IBAD.IPABD_CUR_QTY,
BM.BOQ_ITEM_NO, IBAD.BCI_CODE, BCI.BOQ_CODE
FROM IPA_BOQ_ABSTRCT_DTL IBAD,
BOQ_CONFIG_INF BCI,BOQ_MST BM
WHERE
BM.BOQ_CODE = BCI.BOQ_CODE
AND BCI.BCI_CODE = IBAD.BCI_CODE
and BCI.status = 'Y'
and bm.status = 'Y') I
ON BRI.BCI_CODE = I.BCI_CODE
AND I.TRM_CODE = BRI.TRM_CODE
AND BRI.TRM_CODE =4
group by BRI.CMN_RLTY_MTRL, RRI.RRI_RLTY_RATE, I.BOQ_ITEM_NO,
IBAD.IPABD_CUR_QTY, BRI.BRI_WT_FACTOR, I.TRM_CODE, I.bci_code
order by BRI.CMN_RLTY_MTRL
Results:
TRM should be 11 instead of 4 in the first row.
you getting 4 because you use
AND BRI.TRM_CODE =4
if you remove this criter you can get true result
In your first query, both of the rows you've highlighted have BCI_CODE=1866.
In the second query, you are joining that result set with a number of others (which come from the same tables, which seems odd). In particular, you are joining from the subquery to another table using BCI_CODE, and from there to (SELECT * FROM ipa_boq_abstrct_dtl) IBAD. Since both of the rows from the subquery have the same BCI_CODE, they will join to the same rows in the other tables.
The quantity that you are actually displaying in the second query is from (SELECT * FROM ipa_boq_abstrct_dtl) IBAD, not from the other subquery.
Is the problem simply that you mean to select I.IPABD_CUR_QTY instead of IBAD.IPABD_CUR_QTY?
You might find this clearer if you did not reuse the same aliases for tables at multiple points in the query.

Doctrine, How can I do a select * (all) statememt?

I'm trying to mimic this sql query:
$sql = "SELECT *, log.id as logid, date_format(shipdate,'%m/%d/%Y') as shipdate
FROM log LEFT JOIN sub ON sub.id = sub_id
LEFT JOIN main ON id = main_id WHERE
shipdate >= '$datestart' AND shipdate <= '$dateend' ";
When I put SELECT * in the createQuery function of Doctrine, an error says it doesn't recognize that statement so I tried to grab all the entities by selecting individual ones:
$query = $this->getEntityManager()
->createQuery('
SELECT
m.dano, m.partno, m.batchno,
s.rackno, s.heatcode, s.diecode,
l.shipdate, l.qtyshipped, l.blno, l.id as logid
FROM
Bundle:Sub s
JOIN
s.main m
JOIN
s.log l
WHERE
l.shipdate >= :fromdate and l.shipdate <= :todate
')->setParameter('fromdate', $fromdate)
->setParameter('todate', $todate);
However when I do it this way, it doesn't return all the data that the original queries does. It skips some rows. Is there another way to be selecting all the entity?
You can mimic the following SQL using DQL. I believe that's the best way to do rather than using create query. Select all in DQL is 'select(alias)'. See my
SELECT *, log.id as logid, date_format(shipdate,'%m/%d/%Y') as shipdate
FROM log LEFT JOIN sub ON sub.id = sub_id
LEFT JOIN main ON id = main_id WHERE
shipdate >= '$datestart' AND shipdate <= '$dateend'
DQL
$dql = $qb2->select('m.dano, m.partno, m.batchno,
s.rackno, s.heatcode, s.diecode,
l.shipdate, l.qtyshipped, l.blno, l.id')
->from('YourBundle:Log','l')
->leftJoin('l.sub', 's', Expr\Join::ON, 's.id = l.sub_id')
->leftJoin('l.main', 'm', Expr\Join::ON, 'm.id = l.main_id')
->where('l.shipdate >= :shipdateStart')
->setParameter('shipdateStart', $datestart)
->where('l.shipdate <= :shipdateEnd')
->setParameter('shipdateEnd', $dateend)
By the way your selecting table and joining tables are slightly different in the given sql example compared to your query in create query function. I mimiced what's in your raw SQL which is listed above. Hope this helps you to understand converting SQL in to DQL.
Regards,