Test Data:
memberid MemberID joiningposition packagetype
RPM00000 NULL Root free
RPM71572 RPM00000 Left Royal
RPM323768 RPM00000 Right Royal
RPM715790 RPM71572 Left free
RPM323769 RPM71572 Right free
RPM715987 RPM323768 Left free
RPM323985 RPM323768 Right free
RPM733333 RPM323985 Right free
RPM324444 RPM715987 Right Royal
create a table to store final value
CREATE TABLE [dbo].[Wallatpayout]
(
[childid] [varchar](50) NULL,
[joiningposition] [varchar](50) NULL,
[DateofJoing] [varchar](50) NULL,
[packagetype] [varchar](50) NULL,
[Total] [int] NULL,
[FirstPayoutstatus] [varchar](30) NULL,
[DateofPayout] [datetime] NULL
)
create procedure [dbo].[sunnypro] as
DECLARE @pId varchar(40) = 'RPM00000';
Declare @Id int set @Id=(select id from registration where hildid=@pId)
begin
-- Recursive
CTE WITH R AS (
-- Anchor
SELECT
BU.DateofJoing,
BU.childid,
BU.joiningposition,
BU.packagetype
FROM registration AS BU
WHERE
BU.MemberID = @pId and
BU.joiningposition IN ('Left', 'Right')
or BU.packagetype in('Royal','Platinum','Majestic')
and BU.Id>@id
UNION All
-- Recursive part
SELECT
BU.DateofJoing,
BU.childid,
R.joiningposition,
BU.packagetype
FROM R
JOIN registration AS BU
ON BU.MemberID = R.childid
WHERE
BU.joiningposition IN ('Left', 'Right') and
BU.packagetype in('Royal','Platinum','Majestic')
and BU.Id>@id )
INSERT INTO Wallatpayout
(childid
,packagetype
,joiningposition
,DateofJoing
,Total)
-- Final groups of nodes found
SELECT top 3
R.childid, R.packagetype,
R.joiningposition,
R.DateofJoing,
Total = COUNT_BIG(*) FROM R where R.packagetype in('Royal','Platinum','Majestic')
GROUP BY
R.childid,
R.joiningposition,
R.DateofJoing,
R.packagetype
OPTION (MAXRECURSION 0);
end
This code is helpful for multi-level marketing, to find all left node and right node by passing particular id or parentid.
To start with the correct primary key (single column vs multiple or artificial vs natural) is to use the primary key that is correct for the task.
Some people will tell you to always use an Artificial
or Surrogate
Key. This is a key that is a generated key and has nothing to do with the information it represents. For example an identity column or a GUID. Others will tell you that an artificial key
is the wrong way to go and you want to use a Natural Key
. This is a key that is constructed from one or more columns of the data itself. FYI a key with multiple columns is sometimes called a composite key
. LastName, FirstName for example. Or in your case it looks like you are using a combination of the two. You have an integer ID (presumably artificial) + a year (presumably natural).
I'm not really going to go into the arguments here. You can Google them yourself. In your particular case I would leave your primary keys alone. In my opinion t makes sense to have SurveyId and FieldId columns that are your primary key. These are unique values (I assume) and the tables are basically lookup tables in this particular case. I would however move the Year column out of those tables and into the data
table. If you don’t want to do this then take advantage of the fact that foreign keys can join to a ‘unique key’ as well as a primary key
. A unique key
is an index that enforces uniqueness but is necessarily the primary key. As an added bonus columns in a unique key
can be nullable. In this case your structure would look like this:
CREATE TABLE survey (
surveyID int primary key,
student_name nvarchar(20),
year smallint
)
GO
CREATE UNIQUE INDEX ix_survey ON survey(surveyID, year)
GO
CREATE TABLE fields (
fieldID int primary key,
field_name nvarchar(20),
year smallint
)
GO
CREATE UNIQUE INDEX ix_fields ON fields(fieldID, year)
GO
CREATE TABLE data(
surveyID int,
fieldID int,
year smallint,
value float,
primary key (surveyID, year, fieldID),
foreign key(surveyID, year) REFERENCES survey(surveyID, year),
foreign key(fieldID, year) REFERENCES fields(fieldID, year)
)
GO
I did take the liberty of changing the year column to a smallint which is more than large enough to hold a 4 digit year and only takes 2 bytes instead of 4.
Using the unique key
you can enforce the fact that you want the year columns to be the same while not adding an unnecessary column (the IDs are already unique) to your primary key.
Best Answer
There is no straight-forward way, just linking these tables, to give the result.
The code below gives you the answers, with the bonus that, letting @ColId null, every Client will be processed.
You may think: it is computationally expensive!
Yes, it may seems so. BUT, check the complementary comments after the code snippet, plz.
At first sight, it seems we are asking the SQL Server to
SUM
every invoice,SUM
every payments, and only then computes any overpayment.But, SQL Server 2012 is a hell of a smart beast.
Check the actual execution plan:
The SQL Server query engine is filtering the payment and invoice records BEFORE sumarizing them.
Hence, no performance penalty, although this is not exactly what you asked for - a simple query with tree direct INNER JOINS.
The complete code for this POC follows: