Create table with sum of several conditions from other table - sql

I have another problem, as I need to have a sum in a table based on several data from other table (COST). Solution above brings data on one condition, what I need is to have sum on several conditions from other table:
So I have Cost table, which looks:
CREATE TABLE [dbo].[Cost](
[ID_Cost] [int] NOT NULL,
[Name] [varchar](50) NULL,
[ID_CostCategory] [int] NULL,
[ID_Department] [int] NULL,
[ID_Project] [int] NULL,
[Value] [money] NULL,
) go
then I have Department table, with colums: ID_Department, Name, Plan,
What I want to do is to make in Department table, column Realization which sum values from Cost table based on several conditions (ID_CostCategory and ID_Department and if possible ID_Project)
So in result I get in Department table, column Realization with sum of cost from Cost table per ID_CostCategory and ID_Department.

Related

How to SELECT DISTINCT records with INNER JOIN?

I have two tables Finance Commissions May2021 (FMAY) and Consolidated Client Codes (CCC).
Here is the code for Insert Into: For table FMAY
USE [FinanceCommissions26May2021]
GO
/****** Object: Table [dbo].[Finance_Commissions_May26_2021$] Script Date: 22/06/2021 11:06:26 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Finance_Commissions_May26_2021$](
[Lender Reference] [nvarchar](255) NULL,
[F2] [nvarchar](255) NULL,
[F3] [nvarchar](255) NULL,
[Client] [nvarchar](255) NULL,
[F5] [nvarchar](255) NULL,
[Supplier] [nvarchar](255) NULL,
[Product] [nvarchar](255) NULL,
[Settlement / Inception Date] [nvarchar](255) NULL,
[Base Value] [nvarchar](255) NULL,
[Original Loan Amount] [money] NULL,
[Adviser Split (%)*] [money] NULL,
[F12] [nvarchar](255) NULL,
[Supplier_Amount_(incl GST)] [money] NULL,
[Supplier_Amount_(GST)] [money] NULL,
[Adviser Share (ex GST)] [money] NULL,
[F16] [nvarchar](255) NULL,
[F17] [nvarchar](255) NULL,
[Adviser Share (GST)] [money] NULL,
[Adviser Share (incl GST)] [money] NULL,
[LastNameOnly] [nvarchar](255) NULL,
[FirstNameOnly] [nvarchar](255) NULL,
[FirstFourLastName] [nvarchar](255) NULL,
[ClientCode] [nvarchar](255) NULL,
[IndexMatch] [nvarchar](255) NULL,
[F25] [nvarchar](255) NULL,
[F26] [float] NULL
) ON [PRIMARY]
GO
FMAY
Table FMAY contains the following columns:
commission amounts
a Lender Reference Number
client names (LastName, FirstName).
This report comes in monthly and contains monthly commissions for some of the clients (usually contains 350-400 records).
CREATE TABLE [Finance_Commissions_May26_2021$] (
CommissionAmount,
LenderReferenceNumber,
ClientLastName,
ClientFirstName
)
& here is the code for table CCC:
USE [FinanceCommissions26May2021]
GO
/****** Object: Table [dbo].[Consolidated_ClientCodes$] Script Date: 22/06/2021 11:07:27 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Consolidated_ClientCodes$](
[FirstFourLastName] [nvarchar](255) NULL,
[ClientCode] [nvarchar](255) NULL,
[Client] [nvarchar](255) NULL
) ON [PRIMARY]
GO
CCC
Table CCC contains the following columns:
client names
(different format though - i.e. FirstName,LastName)
a client code (which is a unique identifier (Primary key) assigned to each client.
Client code takes the form of SMIT123.
e.g. for "John, Smith" it's SMIT123
for "Mark, Smith" it's SMIT345, and so on.
i.e. First Four letters of last name followed by a unique 3 digit code.
This table contains Client names and unique Client codes for ALL clients (more than 7000 records)
CREATE TABLE ['20210617145928-Exception - No C$'] (
ClientCode PRIMARY KEY, -- '\w\w\w\w\d\d\d'
FirstName,
LastName
)
The problem
My aim is : To assign this unique Client code to each client within the FMAY table.
Since there was NO common column between tables FMAY and CCC, I created a new column (FirstFourLastName) which parses out FirstFour letters of Last Name (like "SMIT") from both Tables.
Then using this new column (FirstFourLastName), I wrote code for Inner Join in SQL with an aim to assign the Unique "Client Code" to each record in table FMAY.
I am able to get the correct client code assigned but not able to ONLY select distinct records.
My code is:
select
FMAY.[Lender Reference],
CCC.Client,
CCC.ClientCode,
FMAY.FirstFourLastName,
FMAY.[Adviser Share (ex GST)],
FMAY.[Adviser Share (GST)],
FMAY.[Adviser Share (incl GST)],
FMAY.Product
from
[FinanceCommissions26May2021].[dbo].[Finance_Commissions_May26_2021$] FMAY
inner join [FinanceCommissions26May2021].[dbo].['20210617145928-Exception - No C$'] CCC on
FMAY.FirstFourLastName = CCC.FirstFourLastName
The above code is giving me 6300 records, with the correct client code attached to each record though! However, I only need to assign Client Code to the 350-400 records in the FMAY table.
How can I select distinct records for my problem please?
It looks like there might be multiple similar values for FirstFourLastName and with join on FirstFourLastName you're getting every combination possible. For example:
FMAY table
LenderReference
FirstFourLastName
123
smit
456
smit
CCC Table
clientcode
FirstFourLastName
smit123
smit
smit456
smit
Omitting all other columns, the inner join on FirstFourLastName would produce:
LenderReference
clientcode
FirstFourLastName
123
smit123
smit
123
smit456
smit
456
smit123
smit
456
smit456
smit
I would double check that the clientcode is definitely attaching correctly. If LenderReference is unique, you could run distinct count of clientcodes against it.

How to Insert duplicate rows in SQL Server table from excel?

I have an Excel sheet with the following columns:
[API], [BasePrice], [CREATIONDATE], [CREATIONDATETIME],
[DealerCode], [DealerName], [InvoiceNor], [MRP], [MaterialNumber]
I have to insert the data from these columns into a SQL Server table with the same column structure.
The challenge is: [InvoiceNor] and [MaterialNumber] are the columns that should be unique key in the table (order), but the data in Excel in these columns has duplicate rows and the columns [BasePrice], [MRP] in the same rows contain unique values.
How can I insert the data from Excel into a SQL Server table or suggest me the structure of the table?
Current Table structure is:
CREATE TABLE [dbo].[Order]
(
[API] [nvarchar](255) NULL,
[BasePrice] [float] NULL,
[CREATIONDATE] [datetime] NULL,
[CREATIONDATETIME] [datetime] NULL,
[DealerCode] [float] NULL,
[DealerName] [nvarchar](255) NULL,
[InvoiceNor] [float] NOT NULL,
[MRP] [float] NULL,
[MaterialNumber] [float] NOT NULL,
constraint uk_InvoiceNor_MaterialNumber UNIQUE (InvoiceNor
asc,MaterialNumber asc)
)
You cannot insert those unless
you remove the unique keys constraint, or
create a new table (ID Pk, InvoiceNor, MaterialNumber). Remove
InvoiceNor, MaterialNumber from your table and add ID Pk as a foreign
key

MS SQL stored procedure to insert or update total YTD & Previous year invoice totals

I would like to total both current financial YTD invoiced sales & previous financial year invoiced sales on a daily basis for each customer in a MS SQL database and populate a separate table with this information. This information will be available within an application with specific functionality.
There are 3 x tables that contain pertinent information:
Customers (list of all customers in system)
Invoice (all invoice data)
CustomData (custom fields that can be created and populated in an application that interacts with the database)
I am looking for advice on how best to implement a solution that achieves the following:
Checks the current date to see if it is the 1st day of financial year (1st April)
If it is, loop through every record in the customer table that satisfies an argument (live customer) and total the net value - value of credit notes of both the invoices raised in the previous financial year (1st April - 31st March) and current financial YTD (from the 1st April) where the customer ID in the invoice table matches the ID in the customer table.
Then check the CustomData table to see if records for that customerID exist > if they do, update the record with new value (NB null values should = 0), if it doesn't exist, insert the data into the CustomData table.
If the current date is not 1st April, then only total the current financial YTD sales and update/insert into CustomData as required
The tables are constructed as follows (columns that are not relevant to this process have been excluded):
CREATE TABLE [dbo].[Customers]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Code] [varchar](32) NULL,
[CustomerStatus] [tinyint] NOT NULL
CONSTRAINT [DF_Customers_CustomerStatus] DEFAULT ((0)),
CONSTRAINT [PK__Customers]
PRIMARY KEY CLUSTERED ([ID] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[Invoice]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[Datedb] [datetime] NULL,
[AccountNo] [varchar](32) NULL,
[Nett] [float] NOT NULL
CONSTRAINT [DF_InvoiceHead_Nett] DEFAULT ((0)),
[IsCreditNote] [tinyint] NOT NULL
CONSTRAINT [DF_InvoiceHead_IsCreditNote] DEFAULT ((0)),
CONSTRAINT [PK__InvoiceHead]
PRIMARY KEY CLUSTERED ([ID] ASC)
) ON [PRIMARY]
CREATE TABLE [dbo].[CustomData]
(
[ID] [int] IDENTITY(1,1) NOT NULL,
[CustomFieldsContentID] [int] NOT NULL
CONSTRAINT [DF_CustomFieldsData_CustomFieldsContentID] DEFAULT ((0)),
[ModuleID] [int] NOT NULL
CONSTRAINT [DF_CustomFieldsData_ModuleID] DEFAULT ((0)),
[ModuleType] [tinyint] NOT NULL
CONSTRAINT [DF_CustomFieldsData_ModuleType] DEFAULT ((0)),
[ValueNumber] [float] NULL,
[dbTimeStamp] [timestamp] NOT NULL,
CONSTRAINT [PK__CustomFieldsData]
PRIMARY KEY CLUSTERED ([ID] ASC)
) ON [PRIMARY]
The customer relationship is Customers.Code Invoice.AccountNo & CustomData.ModuleID
Customers are live if Customers.CustomerStatus = 2
The CustomData.CustomFieldsContentID = 32 for previous financial year invoiced sales and 33 for YTD invoiced sales.
CustomData.ModuleID is the customer code (Customers.Code & Invoice.AccountNo)
CustomData.ModuleType will be a static value = 18
CustomData.ValueNumber will be the sum of the nett invoice value.
Invoice.IsCreditNote = 1 requires the nett value of that record to be a negative figure.
I'm not familiar with using cursors to loop through the records and also not sure the most efficient way to do this! I don't really know where to start!

Nested SQL Queries 3 levels

I am using MS Access and having troubles writing a query(s) to get my end result. Maybe someone can lend a hand.
I have Projects, Tasks and SubTasks tables. Each table has a related table for "Assignees". meaning a project could be assigned to an employee but the child tasks could be assigned to a different employee and still further the subtasks could then be assigned to other employees.
Now, when displaying this on screen, and I query for an employee that has been assigned to any project/Task/Subtask. I need that data to display but not other data. So for instance if the employee I query for only has been assigned to a task, then that project and task should display, but no additional projects/tasks/ and no subtasks. Likewise, if I query for an employee that only has been assigned to a subtask, then I only want to see the associated project and task. I think I can complete this with a series of queries...i think... but is there a slick method I can use to create this data.
Simply a select query with a series of joins could possibly work, but it doesnt because when an employee has been assigned to a subtask only and not to a project or task.
Thanks for any assistance!
Updated with additional information:
Table Structures:
CREATE TABLE [dbo].[Projects](
[ProjectID] [int] IDENTITY(1,1) NOT NULL,
[ProjectName] [varchar](100) NULL,
[ClientID] [int] NULL,
CREATE TABLE [dbo].[PM_ProjectAssignee](
[AssigneeID] [int] IDENTITY(1,1) NOT NULL,
[ProjectID] [int] NULL,
[EmployeeID] [int] NULL,
CREATE TABLE [dbo].[PM_ProjectTasks](
[ProjectTaskID] [int] IDENTITY(1,1) NOT NULL,
[ProjectID] [int] NULL,
[TaskID] [smallint] NULL,
CREATE TABLE [dbo].[PM_TaskAssignee](
[AssigneeID] [int] IDENTITY(1,1) NOT NULL,
[ProjectTaskID] [int] NULL,
[EmployeeID] [int] NULL,
CREATE TABLE [dbo].[PM_ProjectSubTasks](
[ProjectSubTaskID] [int] IDENTITY(1,1) NOT NULL,
[ProjectTaskID] [int] NULL,
[SubTaskDesc] [varchar](255) NULL,
CREATE TABLE [dbo].[PM_SubTaskAssignee](
[AssigneeID] [int] IDENTITY(1,1) NOT NULL,
[ProjectSubTaskID] [int] NULL,
[EmployeeID] [int] NULL,
With regards to queries I have tried...alot. I was implementing a scenario where I ended up with about a half dozen different queries all culminating into one (some of the queries where built with code to allow filtering) However the last one tried was:
SELECT ProjectID, ProjectName, EmployeeID, ProjectTaskID, EmployeeID, Association, ProjectSubTaskID, EmployeeID
FROM (qrTest3_Project LEFT JOIN qrTest2_Task ON qrTest3_Project.ProjectID = qrTest2_Task.ProjectID) LEFT JOIN qrtest1_SubTask ON qrTest2_Task.ProjectTaskID = qrtest1_SubTask.Association
WHERE (((qrTest3_Project.EmployeeID)=8)) OR (((qrTest2_Task.EmployeeID)=8)) OR (((qrtest1_SubTask.EmployeeID)=8));
the above query included other queries that simply joined each project/task/subtask to their respective assignee table. I can post those as well if needed.
I hope that provides the additional information you need? If not, happy to provide more.
Thanks!
I think I may have figured it out..as I sort of suspected, I was making it a bit more difficult then it needed to be. Simply joins really with criteria gives me the data I need and can work with.
SELECT PM_ProjectAssignee.ProjectID, PM_ProjectTasks.ProjectTaskID, PM_ProjectSubTasks.ProjectSubTaskID
FROM (((PM_ProjectAssignee
LEFT JOIN PM_ProjectTasks
ON PM_ProjectAssignee.ProjectID = PM_ProjectTasks.ProjectID)
LEFT JOIN PM_ProjectSubTasks
ON PM_ProjectTasks.ProjectTaskID = PM_ProjectSubTasks.ProjectTaskID)
LEFT JOIN PM_TaskAssignee
ON PM_ProjectTasks.ProjectTaskID = PM_TaskAssignee.ProjectTaskID)
LEFT JOIN PM_SubTaskAssignee
ON PM_ProjectSubTasks.ProjectSubTaskID = PM_SubTaskAssignee.ProjectSubTaskID
WHERE (((PM_ProjectAssignee.EmployeeID)=14))
OR (((PM_TaskAssignee.EmployeeID)=14))
OR (((PM_SubTaskAssignee.EmployeeID)=14))
GROUP BY PM_ProjectAssignee.ProjectID, PM_ProjectTasks.ProjectTaskID, PM_ProjectSubTasks.ProjectSubTaskID;

Slowly Changing Fact Table?

Background)
I've gone through the process of building a fact table for our inventory data that will in theory act as a nightly snapshot of our warehouse. What is recorded is information such as quantity, weights, locations, statuses, etc. The data is very granular and in many cases not specifically related to a single entity (our source database records inventory data as having three primary keys: licenseplate aka pallet, product, and packaging type - so it has essentially 3 business keys and no surrogate key).
The goal is to be able to have a 100% accurate recreation of our warehouse management system's data, that is viewable for any one day in history. So I can look up and see how many pallets of product XYZ was in location 1234 on the 4th of August.
Question 1)
Now, I have built this fact table to structurally look like a Slowly Changing Dimension, Type 2. Is this wrong? I've been reading up a little on accumulating snapshot fact tables and i'm beginning to question my design. What is the best practice in this situation?
Question 2)
If my design is ok, how do I configure Analysis services so that it recognizes my DateStart and DateEnd columns in the FACT table? I have found some information on how to configure this for dimensions but it does not seem to work/apply to fact tables.
For reference - My fact table's structure (with added notes about columns):
CREATE TABLE [dbo].[FactInventory](
[id] [int] IDENTITY(1,1) NOT NULL, (fact table only surrogate key)
[DateStart] [datetime] NULL, (record begin date)
[DateEnd] [datetime] NULL, (record end date)
[CreateDate] [datetime] NULL, (create date of the inventory record in src db)
[CreateDateId] [int] NULL, (create date dimension key)
[CreateTimeId] [int] NULL, (create time dimension key)
[LicensePlateId] [int] NULL, (pallet id dimension key)
[SerialNumberId] [int] NULL, (serial number id dimension key)
[PackagedId] [int] NULL, (packaging type id dimension key)
[LotId] [int] NULL, (inventory lot id dimension key)
[MaterialId] [int] NULL, (product id dimension key)
[ProjectId] [int] NULL, (customer project id dimension key)
[OwnerId] [int] NULL, (customer id dimension key)
[WarehouseId] [int] NULL, (warehouse id dimension key)
[LocationId] [int] NULL, (location id dimension key)
[LPStatusId] [int] NULL, (licenseplate status id dimension key)
[LPTypeId] [int] NULL, (licenseplate type id dimension key)
[LPLookupCode] [nvarchar](128) NULL, (licenseplate non-system name)
[PackagedAmount] [money] NULL, (inventory amount - measure)
[netWeight] [money] NULL, (inventory netWeight - measure)
[grossWeight] [money] NULL, (inventory grossWeight - measure)
[Archived] [bit] NULL, (inventory archived yes/no - dimension)
[SCDChangeReason] [nvarchar](128) NULL (auditing data for changes)
Typically, in a snapshot fact table you do not have changes.
You usually have a date/time dimension which is used for the granularity of the measurements and not a DateStart/DateEnd. Similarly you do not have any SCD information. The fact snapshot is taken and the Date and Time dimensions are attached to those facts. If those facts repeat identically each month, so be it.
Dealing with determining which facts are valid at a given time is more processing than you really want your DW or your ETL to handle - that kind of design (effective dates, etc) is more effectively used in a live OLTP-type system where complete history is kept in the live system. The point of the DW is to optimize for reporting, not for space, and thus there is a direct snapshot date/time dimension which allows you to easily index and potentially partition the data without a lot of date arithmetic or comparisons.
As far as your dimensional model, be careful that you aren't succumbing to the too-many dimensions problem. Remember that dimensions do not have to correspond to entities in the real world. The choice of how dimensional attributes are grouped into dimension tables should be informed by 1) query needs, 2) data affinity and change behavior, 3) business organization. You might want to look into using one or more junk dimensions.
Before going any further, is inventory really a slowly changing fact?
Edit: Then why not just snapshot every product each day, since that's what you want.
The problem is that fact tables get large and you're throwing EVERYTHING into the fact table unnecessarily. Ideally, the fact table will contain nothing more than foreign keys to dimensions and data only pertaining to the fact at hand. But some of the columns you've outlined look like they belong in one of the dimensions tables whereas
For instance, the license plate information. Status, type, and lookup code. Likewise with netWeight/grossWeight. They should be derivable from the product dimension and PackagedAmount.
CREATE TABLE [dbo].[FactInventory](
[id] [int] IDENTITY(1,1) NOT NULL, (fact table only surrogate key)
[day] [int] NULL, (day dimension key, grain of a day)
[CreateDateId] [int] NULL, (create date dimension key)
/* I take these are needed?
* [CreateTimeId] [int] NULL, (create time dimension key)
* [CreateDate] [datetime] NULL, (create date of the inventory record in src db)
*/
[LicensePlateId] [int] NULL, (pallet id dimension key)
/* Now THESE dimension columns...possibly slowly changing dimensions?
[LPStatusId] [int] NULL, (licenseplate status id dimension key)
[LPTypeId] [int] NULL, (licenseplate type id dimension key)
[LPLookupCode] [nvarchar](128) NULL, (licenseplate non-system name)
*/
[SerialNumberId] [int] NULL, (serial number id dimension key)
[PackagedId] [int] NULL, (packaging type id dimension key)
[LotId] [int] NULL, (inventory lot id dimension key)
[MaterialId] [int] NULL, (product id dimension key)
[ProjectId] [int] NULL, (customer project id dimension key)
[OwnerId] [int] NULL, (customer id dimension key)
[WarehouseId] [int] NULL, (warehouse id dimension key)
[LocationId] [int] NULL, (location id dimension key)
[PackagedAmount] [money] NULL, (inventory amount - measure)
[netWeight] [money] NULL, (inventory netWeight - measure)
[grossWeight] [money] NULL, (inventory grossWeight - measure)
[Archived] [bit] NULL, (inventory archived yes/no - dimension)
[SCDChangeReason] [nvarchar](128) NULL (auditing data for changes)