How to connect 2 MSSQL queriues with c#? - sql-server-2005

I have following question - I need to build category list from unique department name and under each department list articles, which belongs to it.
I wrote 2 mssql queries:
1) Selecting unique department's name (table consists of id and string name):
select distinct (fs.ob_no), fs.c_name as fs_c_name from et_filials_suggest fs order by fs.ob_no
and getting something like this:
ob_no fs_c_name
244400 IT Department
244401 HR Department
2) Than I select articles:
select s.ob_no as s_ob_no,
s.c_name as s_c_name,
s.e_fio,
s.e_text_header,
s.e_datetime,
s.e_link_filial,
fs.c_name
from et_suggest s
inner join et_filials_suggest fs on fs.ob_no = s.e_link_filial
where s.c_visible=1
AND s.e_lean_flag=1
AND fs.c_visible=1
and getting something like this:
s.ob_no | s.c_name | s.e_fio | s.e_text_header | s.e_datetime |s.e_link_filial | fs.c_name
458713 | Article_sys_name | Me |Aricle_vis_name | 2013-11-12 00:00:00.000 |44410 | IT deparment
And here goes the problem, I don't understand how to make list, e.g.:
IT Department
Article 1
Article 2
HR Department
Article 3
....
Here I get list of departments:
<%#DataBinder.Eval(Container.DataItem, "fs_c_name")%>
But how can I connect it with articles? Seems to me that I should set variable in first query but how can I use it later?
Here is the full example of code I've made - article is limited to 1 and it displays under each department without connection to it:
<mso:Query ID="Query1" runat="server" CommandType="Text" CommandText="select distinct (fs.ob_no), fs.c_name as fs_c_name from et_filials_suggest fs order by fs.ob_no">
<ItemTemplate>
<b><%#DataBinder.Eval(Container.DataItem, "fs_c_name")%></b><br />
<mso:Query ID="Query1" runat="server" CommandType="Text" CommandText="
select top (1)
s.ob_no as s_ob_no,
s.c_name as s_c_name,
s.e_fio,
s.e_text_header,
s.e_datetime,
s.e_link_filial,
fs.c_name
from et_suggest s
inner join et_filials_suggest fs on fs.ob_no = s.e_link_filial
where s.c_visible=1
AND s.e_lean_flag=1
AND fs.c_visible=1">
<ItemTemplate>
<%#DataBinder.Eval(Container.DataItem, "s_c_name")%><br />
</ItemTemplate>
</mso:Query>
</ItemTemplate>
</mso:Query>
Thanks in advance for any kind of help.
UPDATE:
Well i have an idea - if i change in 2nd query inner join to left join and add where clause i can get list of articles for department:
select
s.ob_no as s_ob_no,
s.c_name as s_c_name,
s.e_fio,
s.e_text_header,
s.e_datetime,
s.e_link_filial,
fs.c_name
from et_suggest s
left join et_filials_suggest fs on fs.ob_no = s.e_link_filial
where s.c_visible=1
AND s.e_lean_flag=1
AND fs.c_visible=1
AND s.e_link_filial=244411
But i still don't know how to change number from:
AND s.e_link_filial=244411
to variable from the first query:
select distinct (fs.ob_no), fs.c_name as fs_c_name from et_filials_suggest fs order by fs.ob_no

Remove the line
AND s.e_link_filial=244411
and all records will be returned
you should instead add the following line
ORDER BY s.e_link_filial=244411
By the way, in web page development, while binding grid view with this type of information, I use a different approach.
Let me know if you are interested to know, I will update my answer.

Related

SQL query for crystal reports produces duplicate results

I created 3 tables TstInvoice, TstProd, TstPersons and added some data:
INVOICE_NBR CLIENT_NR VK_CONTACT
A10304 003145 AT
A10305 000079 EA
A10306 004458 AT
A10307 003331 JDJ
PROD_NR INVOICE_NBR
P29366 A10304
P29367 A10304
P29368 A10305
P29369 A10306
P29370 A10306
P29371 A10307
PERS_NR INITIALEN STATUS PERSOON
0001 AT 7 Alice Thompson
0002 EA 1 Edgar Allen
0003 JDJ 1 John Doe Joe
0004 AT 1 Arthur Twins
The parameter that is passed to the crystal report is the INVOICE_NBR.
On my crystal report I put some fields from the databases and one sql expression:
(
SELECT "TstPersons"."PERSOON" FROM "TstPersons"
WHERE "TstPersons"."INITIALEN" = "TstInvoice"."VK_CONTACT" AND "TstPersons"."STATUS" = 1
)
The full query that is generated:
SELECT "TstInvoice"."INVOICE_NBR", "TstInvoice"."CLIENT_NR", "TstPersons"."STATUS", "TstPersons"."PERSOON", "TstProd"."PROD_NR", "TstProd"."INVOICE_NBR", (
SELECT "TstPersons"."PERSOON" FROM "TstPersons"
WHERE "TstPersons"."INITIALEN" = "TstInvoice"."VK_CONTACT" AND "TstPersons"."STATUS" = 1
)
FROM ("GCCTEST"."dbo"."TstInvoice" "TstInvoice" INNER JOIN "GCCTEST"."dbo"."TstProd" "TstProd" ON "TstInvoice"."INVOICE_NBR"="TstProd"."INVOICE_NBR") INNER JOIN "GCCTEST"."dbo"."TstPersons" "TstPersons" ON "TstInvoice"."VK_CONTACT"="TstPersons"."INITIALEN"
WHERE "TstInvoice"."INVOICE_NBR"='A10304'
The result is as shown in the screenshot:
As you can see the TstPersons.PERSOON field is populated with Alice Thompson and the sql expression field is correctly populated with Arthur Twins. However, I would like only to see the prod_nr once. With this query it produces the prod numbers twice because of the double entry for "AT" despite the fact that I ask for only status 1. I could just delete the old entry but I want to know if it's possible this way.
* edit * I added the status = 1 to the "record selection formula editor" and that seems to work. Not need the sql expression field at all. Not sure if this is the correct way to go though.
So now it looks like this:
SELECT "TstInvoice"."INVOICE_NBR", "TstInvoice"."CLIENT_NR", "TstPersons"."STATUS", "TstPersons"."PERSOON", "TstProd"."PROD_NR", "TstProd"."INVOICE_NBR"
FROM ("GCCTEST"."dbo"."TstInvoice" "TstInvoice" INNER JOIN "GCCTEST"."dbo"."TstProd" "TstProd" ON "TstInvoice"."INVOICE_NBR"="TstProd"."INVOICE_NBR") INNER JOIN "GCCTEST"."dbo"."TstPersons" "TstPersons" ON "TstInvoice"."VK_CONTACT"="TstPersons"."INITIALEN"
WHERE "TstInvoice"."INVOICE_NBR"='A10304' AND "TstPersons"."STATUS"=1
You have a very weak join in your query due to the duplicate values found in the INITIALEN column. Using the STATUS = 1 criteria is a work-around more than a solution because if you ever need to report on an invoice where the contact has a status other than 1, you will need to modify the report's design to allow your join to work because the STATUS value is not found on the invoice to allow a proper join to occur.
You are also running a risk of this work-around breaking down completely should you have another contact with both the same initials and status values as another.
The correct way to solve this problem would be to join TstInvoice to TstPersons through a field that has unique values. The PERS_NR column appears to be a good choice for this.
This is also going to require a redesign of the TstInvoice table to include the PERS_NR column as a Foreign Key.
A stronger join between invoices and persons would also remove the need for that sub-query in you selection statement. This would simplify your query down to the following:
SELECT "TstInvoice"."INVOICE_NBR", "TstInvoice"."CLIENT_NR", "TstPersons"."STATUS", "TstPersons"."PERSOON", "TstProd"."PROD_NR", "TstProd"."INVOICE_NBR"
FROM "GCCTEST"."dbo"."TstInvoice" "TstInvoice"
INNER JOIN "GCCTEST"."dbo"."TstProd" "TstProd"
ON "TstInvoice"."INVOICE_NBR"="TstProd"."INVOICE_NBR"
INNER JOIN "GCCTEST"."dbo"."TstPersons" "TstPersons"
ON "TstInvoice"."PERS_NR"="TstPersons"."PERS_NR"
WHERE "TstInvoice"."INVOICE_NBR"='A10304'

Select Last movement for each ID in Access

I am working on a MS-Access table, and would like to have a query to result all the information on the last entry from a certain id.
My table (DEPOSIT_MOVEMENTS) is the following:
MOV_CODE | WORK | DEPOSIT_CODE | TYPE | DATE | DESTINATION
I am looking to obtain for each DEPOSIT_CODE the latest register (on date), and obtain the *MOV_CODE so that I can get the DESTINATION of the item.
DEPOSIT_CODE may have many MOV_CODE on different dates.
I have tried with different options posted on stackoveflow, but I coudl not get any of these to work properly.
Right now I am trying with the GROUP BY, but cannot get it working.
SELECT t1.[DEPOSIT_CODE], MAX(t1.[DATE]), t1.[MOV_CODE]
FROM [DEPOSIT_MOVEMENTS] AS t1
GROUP BY t1.[DEPOSIT_CODE];
Any help or guidance is welcome.
Kind regards,
Here is one method:
SELECT dm.*
FROM [DEPOSIT_MOVEMENTS] AS dm
WHERE dm.DATE = (SELECT MAX(dm2.DATE)
FROM [DEPOSIT_MOVEMENTS] AS dm2
WHERE dm2.DEPOSIT_CODE = dm.DEPOSIT_CODE
);

How to Group_Concat with a 3-table JOIN for genealogy

I am failing to grasp how I can get the following outcome. I thought perhaps via GROUP_CONCAT, but I am also joining on 3 tables, and unclear on the correct syntax or if this is even the best approach.
Generic table layout:
Table Users: user_id | first | last
Table Orgs org_id | org_name
Table Relationship user_id | org_id | start_year | end_year
The relationship table has MANY entries, that may be associated with that specific user_id.
I need to get the User columns: id, first, last. I'd like to try and group the org data into 1 concatenated, delimited field. Maybe a double group_concatenation is needed? Which would consist of the org_id, org_name, start_year & end_year for all records in the relationship table that match the user_id. I'm hoping for an output like this:
Each '|' represents a new column/piece of data.
If there was only 1 org_id associated with the user_id, the output would be (similar) to:
user_id | first | last | org_id-org_name-start_year-end_year
If there were more than 1 org found/associated with that user_id, the output would have more concatenated/delimited data in the same column:
user_id | first | last | org_id-org_name-start_year-end_year^org_id-org_name-start_year-end_year^org_id-org_name-start_year-end_year
(Notice the '-' delimiter between values and the '^' delimiter between new 'org-grouped' data.)
When I grab that data, I can then just break it up (on the backend/PHP side of things) into an array or whatever.
I'm not sure how I can GROUP_CONCAT (if that is even the best approach here?) while I have to JOIN on 3 separate tables.
This is not my REAL query. (I'm not sure if I should post it, as I do not want to cause any confusion as it does NOT match my dummy table/column names.)
I just wanted to show my attempt that gets me 3 individual rows, (using my JOINS) but no GROUP_CONCAT stuff:
SELECT genealogy_users.imis_id, genealogy_users.full_name,
genealogy_users.member_email, genealogy_orgs.org_id,
genealogy_orgs.org_name, genealogy_relations.user_id,
genealogy_relations.relation_type, genealogy_relations.start_year,
genealogy_relations.end_year
FROM genealogy_users
INNER JOIN genealogy_relations ON genealogy_users.imis_id = genealogy_relations.user_id
INNER JOIN genealogy_orgs ON genealogy_relations.org_id = genealogy_orgs.org_id
WHERE genealogy_users.imis_id = '00003';
UPDATE:
Well I seemed to have fudged my way through it. But I'm not sure how legit this is.
Its -ALMOST- there. I believe I still need a JOIN or something? Since the genealogy_orgs.org_id = '84864' is hardcoded, and it should NOT be. Maybe it needs to come from a JOIN or something?
SELECT genealogy_users.*,
(SELECT GROUP_CONCAT(org_id,'-',
(SELECT org_name FROM genealogy_orgs WHERE genealogy_orgs.org_id = '84864'),
'-',start_year,'-',end_year,'^')
FROM genealogy_relations WHERE genealogy_relations.user_id = genealogy_users.imis_id
) AS alumni_list
FROM genealogy_users
WHERE genealogy_users.imis_id = '00003';
UPDATE 2:
My final attempt, which I think is getting me what I need. (But it's late, and I'll check back tomorrow and look at things more closely.)
SELECT genealogy_users.imis_id, genealogy_users.full_name,
genealogy_users.member_email, genealogy_orgs.org_id,
genealogy_orgs.org_name, genealogy_relations.user_id,
genealogy_relations.relation_type, genealogy_relations.start_year,
genealogy_relations.end_year,
(SELECT GROUP_CONCAT(org_id,'-',org_name,'-',start_year,'-',end_year,'^')
FROM genealogy_relations
WHERE genealogy_relations.user_id = genealogy_users.imis_id
) AS alumni_list
FROM genealogy_users
INNER JOIN genealogy_relations ON genealogy_users.imis_id = genealogy_relations.user_id
INNER JOIN genealogy_orgs ON genealogy_relations.org_id = genealogy_orgs.org_id
WHERE genealogy_users.imis_id = '00003';
Is there anything to make note of in the above attempt? Or is there a better approach? Hopefully something easily readable so it makes sense?

SSRS 2008 R2 / SQL - How to filter groups but keep detail data?

EDIT - i'm reposting this question in an attempt to explain what i mean better
I'm using SQL 2008 R2 and I work for a retail department store and we need a report to show all the sales orders made in each department, and sections of those departments.
What i want is to group up all the sales order lines by department and section, but remove only the sections that have a total sales value of less than £50. I still want to see order lines that are over £50, though.
Here is an example of what i currently have:
Data before filtering
I want to remove the Accessories section and all lines contained within it, as it has a total section value of less than £50. So i would want it looking like this after filtering:
Data after filtering
Here is my code:
SELECT department.department_name
,section.section_name
,sales_order_detail.sales_order_number
,sales_order_detail.sales_order_line
,LineValue
FROM
sales_order_detail INNER JOIN stock_item ON sales_order_detail.stock_item_code = stock_item.stock_item_code
INNER JOIN style ON stock_item.style_code = style.style_code
INNER JOIN department ON style.dept_code = department.department_code
INNER JOIN section ON style.section_code = section.section_code AND style.dept_code = section.department_code AND department.department_code = section.department_code
Can you please explain all the ways this can be done. I've tried using GROUP BY and HAVING but that then filters out all my sales order lines. I've tried using a Group Filter in the visual studio report design surface which removes the lines but then aggregates calculated at the Department group scope don't take into account the lines removed at the section level.
I appreciate any help i can get on this.
Jacob
As you are using 2008R2, you can use the magic that are Windowed Functions to calculate the total of the group that the row belongs to (the partition part of the over clause below) and then wrap your query into a filtering select statement. Not having your data this is obviously not tested, but it should work:
select department_name
,section_name
,sales_order_number
,sales_order_line
,LineValue
,GroupTotal
from(
select d.department_name
,se.section_name
,sod.sales_order_number
,sod.sales_order_line
,sod.qty_ordered * sod.selling_price AS LineValue
,sum(sod.qty_ordered * sod.selling_price) over (partition by d.department_name
,se.section_name
) as GroupTotal
from sales_order_detail sod
inner join stock_item si
on sod.stock_item_code = si.stock_item_code
inner join style s
on stock_item.style_code = s.style_code
inner join department d
on s.dept_code = d.department_code
inner join section se
on s.section_code = se.section_code
and s.dept_code = se.department_code
and d.department_code = se.department_code
) a
where GroupTotal > 50

SQL Access 2007/2010 Selecting Max Date with Distinct ID

I believe a lot of people have already asked this question as I have read all the topic from here. But the Problem is I have 3 related tables instead of 2 and I'm not sure how to code for that
I have a table: tbl_Instruments, tbl_Record and tbl_Cal_By.
tbl_Instruments has all the instruments information including their ID.
tbl_Cal_By has the information for whoever is calibrating the tool.
tbl_Records has all the instruments Records and their Calibration date. It inherits the ID from tbl_Instruments as Inst_ID and the Name from tbl_Cal_By as Name_ABBR.
tbl_Instruments: ID, Type
tbl_Cal_By: Cal_ID, Name_ABBR
tbl_Records: Record_ID, Inst_ID, Cal_Date, Name_ABBR
Here is my code.
SELECT tbl_Records.Inst_ID
,tbl_Instruments.Type
,Max(tbl_Records.Cal_Date) AS MaxOfCal_Date
,tbl_Cal_By.Name_ABBR
FROM tbl_Cal_By
RIGHT JOIN (
tbl_Instruments INNER JOIN tbl_Records ON tbl_Instruments.ID = tbl_Records.Inst_ID
) ON tbl_Cal_By.ID = tbl_Records.BY
GROUP BY tbl_Records.Inst_ID
,tbl_Instruments.Type
,tbl_Cal_By.Name_ABBR;
Desired result:
Any help will be appreciated!
You can do this in several methods, one of the is exists :
SELECT tbl_Records.Inst_ID
,tbl_Instruments.Type
,tbl_Records.Cal_Date AS MaxOfCal_Date
,tbl_Cal_By.Name_ABBR
FROM tbl_Cal_By
RIGHT JOIN (
tbl_Instruments INNER JOIN tbl_Records ON tbl_Instruments.ID = tbl_Records.Inst_ID
) ON tbl_Cal_By.ID = tbl_Records.BY
WHERE NOT EXISTS(SELECT 1 FROM tbl_Records t
WHERE t.Inst_ID = tbl_Instruments.ID
AND t.Cal_date > tbl_Records.Cal_Date)
I'm not entirely sure about access syntax and aliases.. so maybe you will have to adjust it a little bit - like alias the first tbl_records so it will recognize it, or maybe it will work..