How to retrieve multiple aggregate columns from SQL Server in a SQL View/Access Query (pref SQL View) - sql-server

I have a table tblRecords, into this table are inserted 3500 records each day. tblRecords has a foreign key linking it to tblUpload. Each Row is identified, apart from a generic ID column, by a REF (ie: XYDG74G) and the Foreign Key Column (ie: 345) that links it to tblUpload.
The circa 3500 rows that are uploaded each day are the same rows as were uploaded from the previous day (with updates) as well as additional, new entries from the last 24 hrs.
Each tblRecord row can be flagged (BIT column) as MissCustName and MissCustNameFixed. I view the tblRecord rows by tblUpload, that is to say I “Show me all (3500+) records uploaded today”. I want, along with the actual columns in tblRecord to see two columns, CountOfPrevMissCustName and CountOfPrevMissCustNameFixed
ID - Ref - CustName - CountofPrevMissCustName- CountofPrevMissCustNameOK
1 - AASD001 - <NULL> - 14 - 12
2 - ZRFG789 - Joe Bloggs - 10 - 8
3 - YERF777 - Mary Blyge - 0 - 0
Missing Customer Name counts the total records (historical) for that Transaction where Missing Customer Name is flagged as TRUE. `MissNameFixed does the same.
Record 1 has previously had 14 missing customer name flags and 12 MissNameCustNameOK flags, but is still missing the customer name.
Record 2 has previously had 10 missing customer name flags, and 8 MissNameCustNameOK flags and currently has a customer name.
Record 3 has never had any missing customer name flags and hence no MissNameCustNameOK flags and currently has a name.
What would be the most efficient (quickest and less stress on SQL Server) to implement these 'dcount' style columns. Trying a dcount column within Access is painfully slow 9See below), as is using DAO recordsets in Access.
SELECT *, dcount("RecordID","tblRecordsHistorical","Ref=" & Ref & " AND CustName is null) as CountofPrevMissCustName, dcount("RecordID","tblRecordsHistorical","Ref=" & Ref & " AND CustName is not null) as CountofPrevMissCustNameOK from tblRecords
I would ideally like to be able to create some kind of view, that I could load, then use to do a bulk update on the table.
I will only ever work on the latest batch of tblRecords so once the CountOf... physical columns have been updated once, they don't need to be again.
Thnx

Related

Editing MS SQL DB with 20 tables to 1 table without data lost

Hello I don't know how to do changes of my MS SQL DB to integrate it to work with new software.
The case is related with software limitations.
Our old software can write, read and work with MS SQL DB with multiple tables but the new software understand only from one table or one view table.
My question is how can I edit my MS SQL DB form 20 tables to do it to be one DB with one table with all data from 20 tables and columns without data lost?
And one last question is true about View Tables in MS SQL that they are read only for applications and software?
Why is it not a good idea to put data from all your 20 tables into one table ?
I will try to explain with an example, since I do not know your database I just think of some tables here
suppose you have a table Clients
ClientID Name Street City
1 John ChuchStreet Denver
2 Anna FlowerStreet Boston
and a table Products
ProductID Name Price
1 Mouse 10
2 Keyboard 30
3 Usb Cable 10
and table Orders
OrderID OrderNumber CLientID TotalAmount
1 123 1 10
2 345 1 20
3 678 2 30
and finally table OrderDetail
OrderDetailID OrderID ProductID Quantity
1 1 1 1
2 2 1 1
3 2 3 1
4 3 2 1
Now to put this into one table, you could do this
ID ClientName ClientStreet ClientCity OrderNumber TotalAmount ProductName ProductPrice ProductQuantity
1 John ChurchStreet Denver 123 10 Mouse 10 1
1 John ChurchStreet Denver 345 20 Mouse 10 1
2 John ChurchStreet Denver 345 20 Usb Cable 10 1
3 Anna FlowerStreet Boston 678 30 Keyboard 30 1
Now you can already see the redundancy,
you need to repeat the address of each customer, time and time again in your table
you need to repeat the ordernumber and total amount time and time again
you need to repeat the productname and price time and time again
Now suppose that John moves to another address, now you have to search for John in every row in the table, and adjust the address
Now suppose a productname changes, again you have to search all rows and update
That is lots of work, very inefficient, and guaranteed to go wrong at some point
Now I only used 4 tables in this example, can you image what will happen if you would merge 20 tables into 1 ?
And the redundancy is not your only problem, what if you want to look at a client, what row should you use ?
What if you want to look at an order, what row should you use ?
What if you want to look at a product, what row should you use ?
In this one table design, you cannot identify a single row for customer, or order anymore. That is because each row contains everyting, there is no distinct row anymore for a customer, or a product, or an order...
Merging all tables into one big table is simply not possible to maintain
Hi thank you for your answers!
I am trying to integrate old ms sql db to new IDFLOW Software.
This software understand from ms sql db but only from one table but my old db contains 18 tables....
IDFLOW understand from views, but it is not good to work with views, they are okay for card design in IDFLOW, but views are not okay to write new data in db from IDFLOW interface , because in views it is not possible to write new data in db!
And now I started to think to create one db with one table with all columns, and I completed it successfully!
Now in my sql server I am with two db, old db and new db.
Now I don't know how to export data from old db and import it to new db?
I am talking about export column2 from table1 from db1 and import it in column2 from table1 from db2 ....
and so and so ........... column2 from table2 from db1 and import it in column3 from table1 from db2 ............
and so and so .... column 5 from table18 from db1 and import it in column10 form table1 from db2.
Is it possible to do that?
Okay, but IDFLOW works only with one table...
And I asked Jolly and they say utilize your DB for one table.
IDFLOW is a software for ID CARDS .
I think it is possible to use one db with one table and all columns for employee information.
The goal is.. in IDFLOW enter all data for new employee, when you enter data from IDFLOW interface they go into MS SQL DB and all fields from DB are in card design configured, and when you select records for one employee from IDFLOW interface (from db) you can print ID CARD with all data for employee.
The question is how to migrate old records from old db in new.
It is not big database, it is only 6 GB from 2006.
And we use it only for printing id cards.

Creating a global ID for every row in multiple tables for notifications

I'm designing what is essentially an accounting/retailing application for MS SQL Server 2016. I have ~75 core data object types, each in their own respective table (users, organizations, invoices, payments, etc.).
What I need to create is a notification system,
e.g. "Steve paid invoice 1234", "Bob purchased product XYZ", etc. What I was going to create was a "notification types" table:
NotificationTypes:
id message
11 "{0} paid invoice {1]"
12 "{0} purchased product {1]"
...
and then have two corresponding tables that store each notification event's info, and then the values for that notification message. So for example for "Steve paid invoice 1234":
NotificationEvent:
id notificationType (FK) occured
21 11 2016-01-01 00:00:00
NotificationEventValues:
id notificationEvent (FK) XXXXX
31 21 (FK reference to Steve in users table)
32 21 (FK reference to invoice 1234 in invoices table)
Now since I can't create generic foreign keys for NotificationEventValues.XXXXX, I was going to have a single 'dataObjects' table that has FK columns for all 75 data types I have, with only one of the 'data type' columns having a value per row.
This way, every instance of a data object in my database has a unique ID I can reference in the notification field - which will mean a huge table given it has a unique ID for basically every row in the other 75 tables. The other downside is it means for every user, invoice, any 'data object', I'm wasting significant amounts of space since space will be reserved for ID references for the other 74 null-valued columns (since they're fixed size IDs and not variable).
ASK:
Is there a better way to achieve my 'global' identifier across all the tables? Or a better way to handle the notification system to avoid this problem?
Create triggers in all table that will insert a record in a table say KeyMaster with one column key which will also be the primry key whenever a record is inserted in any table. The value inserted in this table will be in the format _. For example if a record is inserted in user table with id 1 then the record inserted in KeyMaster table will be 'user_1'. Similarly if a record is inserted in invoice table with id 1 then the recor inserted in KeyMaster table will be 'invoice_1'.
In your NotificationEventValues table you will need only three columns id,notificationEvent and key (FK reference to KeyMaster table).
For getting corresponding record you need to write query similar to below:
select *
from NotificationEventValues n
inner join users u on 'user_' + u.id = n.key

Dynamic pivot table sql server 2008

I would like to do data mining. But my data is not useful.
my table structure is something like:
date customerid age residence prosubsclassid productid
----------------------------------------------------------------------------
21.11.2001 123232323 a b 2099 23232322
amount asset sales
------------------------
4 34 56
Now I have to show the data in this way:
prosubsclassid 130207 130208 130209
------ ------ ------
1413232 1 3 1
3435545 2 1 2
3534344 3 1 sum(amount)
Column(customerid)
I want to convert to tabular form in my data.
There is no automatic way to do this. There are support for pivot in SQL server, but the columns still needs to be specified.
Depending on if you want to have a text report or a table with dynamic columns I would group the data per date and prosubsclassid and then using a cursor to build the data.
If you want a dynaic table build a dynamic sql query based on the grouped data and run Exec.
If you want text report, just concatenate the string data the way you want per line into
a temp table with one textcolumn and when you are done, select the table.

Database schema for end user report designer

I'm trying to implement a feature whereby, apart from all the reports that I have in my system, I will allow the end user to create simple reports. (not overly complex reports that involves slicing and dicing across multiple tables with lots of logic)
The user will be able to:
1) Select a base table from a list of allowable tables (e.g., Customers)
2) Select multiple sub tables (e.g., Address table, with AddressId as the field to link Customers to Address)
3) Select the fields from the tables
4) Have basic sorting
Here's the database schema I have current, and I'm quite certain it's far from perfect, so I'm wondering what else I can improve on
AllowableTables table
This table will contain the list of tables that the user can create their custom reports against.
Id Table
----------------------------------
1 Customers
2 Address
3 Orders
4 Products
ReportTemplates table
Id Name MainTable
------------------------------------------------------------------
1 Customer Report #2 Customers
2 Customer Report #3 Customers
ReportTemplateSettings table
Id TemplateId TableName FieldName ColumnHeader ColumnWidth Sequence
-------------------------------------------------------------------------------
1 1 Customer Id Customer S/N 100 1
2 1 Customer Name Full Name 100 2
3 1 Address Address1 Address 1 100 3
I know this isn't complete, but this is what I've come up with so far. Does anyone have any links to a reference design, or have any inputs as to how I can improve this?
This needs a lot of work even though it’s relatively simple task. Here are several other columns you might want to include as well as some other details to take care of.
Store table name along with schema name or store schema name in additional column, add column for sorting and sort order
Create additional table to store child tables that will be used in the report (report id, schema name, table name, column in child table used to join tables, column in parent table used to join tables, join operator (may not be needed if it always =)
Create additional table that will store column names (report id, schema name, table name, column name, display as)
There are probably several more things that will come up after you complete this but hopefully this will get you in the right direction.

MS Access row number, specify an index

Is there a way in MS access to return a dataset between a specific index?
So lets say my dataset is:
rank | first_name | age
1 Max 23
2 Bob 40
3 Sid 25
4 Billy 18
5 Sally 19
But I only want to return those records between 'rank' 2 and 4, so my results set is Bob, Sid and Billy? However, Rank is not part of the table, and this should be generated when the query is run. Why don't I use an autogenerated number, because if a record is deleted, this will be inconsistent, and what if I wanted the results in reverse!
This obviously very simple, and the reason I ask is because I am working on a product catalogue and I am looking for a more efficient way of paging through the returned dataset, so if I only return 1 page worth of data from the database this is obviously going to be quicker then return a complete set of 3000 records and then having to subselect from that set!
Thanks R.
Original suggestion:
SELECT * from table where rank BETWEEN 2 and 4;
Modified after comment, that rank is not existing in structure:
Select top 100 * from table;
And if you want to choose subsequent results, you can choose the ID of the last record from the first query, say it was ID 101, and use a WHERE clause to get the next 100;
Select top 100 * from table where ID > 100;
But these won't give you what you're looking for either, I bet.
How are you calculating rank? I assume you are basing it on some data in another dataset somewhere. If so, create a function, do a table join, or do something that can calculate rank based on values in other table(s), then you can do queries based on the rank() function.
For example:
select *
from table
where rank() between 2 and 4
If you are not calculating rank based on some data somewhere, there really isn't a way to write this query, and you might as well be returning three random rows from the table.
I think you need to use a correlated subquery to calculate the rank on the fly e.g. I'm guessing the rank is based on name:
SELECT T1.first_name, T1.age,
(
SELECT COUNT(*) + 1
FROM MyTable AS T2
WHERE T1.first_name > T2.first_name
) AS rank
FROM MyTable AS T1;
The bad news is the Access data engine is poorly optimized for this kind of query; in my experience, performace will start to noticeably degrade beyond a few hundred rows.
If it is not possible to maintain the rank on the db side of the house (e.g. high insertion environment) consider doing the paging on the client side. For example, an ADO classic recordset object has properties to support paging (PageCount, PageSize, AbsolutePage, etc), something for which DAO recordsets (being of an older vintage) have no support.
As always, you'll have to perform your own timings but I suspect that when there are, say, 10K rows you will find it faster to take on the overhead of fetching all the rows to an ADO recordset then finding the page (then perhaps fabricate smaller ADO recordset consisting of just that page's worth of rows) than it is to perform a correlated subquery to only fetch the number of rows for the page.
Unfortunately the LIMIT keyword isn't available in MS Access -- that's what is used in MySQL for a multi-page presentation. If you can write an order key into the results table, then you can use it something like this:
SELECT TOP 25 MyOrder, Etc FROM Table1 WHERE MyOrder in
(SELECT TOP 55 MyOrder FROM Table1 ORDER BY MyOrder DESC)
ORDER BY MyOrder ASCENDING
If I understand you correctly, there is ionly first_name and age columns in your table. If this is the case, then there is no way to return Bob, Sid, and Billy with a single query. Unless you do something like
SELECT * FROM Table
WHERE FirstName = 'Bob'
OR FirstName = 'Sid'
OR FirstName = 'Billy'
But I think that this is not what you are looking for.
This is because SQL databases make no guarantee as to the order that the data will come out of the database unless you specify an ORDER BY clause. It will usually come out in the same order it was added, but there are no guarantees, and once you get a lot of rows in your table, there's a reasonably high probability that they won't come out in the order you put them in.
As a side note, you should probably add a "rank" column (this column is usually called id) to your table, and make it an auto incrementing integer (see Access documentation), so that you can do the query mentioned by Sev. It's also important to have a primary key so that you can be certain which rows are being updated when you are running an update query, or which rows are being deleted when you run a delete query. For example, if you had 2 people named Max, and they were both 23, how you delete 1 row without deleting the other. If you had another auto incrementing unique column in there, you could specify the unique ID in your query to delete only one.
[ADDITION]
Upon reading your comment, If you add an autoincrement field, and want to read 3 rows, and you know the ID of the first row you want to read, then you can use "TOP" to read 3 rows.
Assuming your data looks like this
ID | first_name | age
1 Max 23
2 Bob 40
6 Sid 25
8 Billy 18
15 Sally 19
You can wuery Bob, Sid and Billy with the following QUERY.
SELECT TOP 3 FirstName, Age
From Table
WHERE ID >= 2
ORDER BY ID

Resources