选择前N个后选择最后一个记录

时间:2019-09-07 02:46:27

标签: sql-server tsql

我想选择前N条记录后仅选择最后一条记录。简而言之,我只想选择一个特定的记录。我尝试使用子查询,但这不是很好。它给出了一个错误

  

子查询返回了多个值。

我知道我做过的子查询提供了多个值,但是我该如何在前N条记录中选择一个特定记录?

select top 1 (select top 5 Work_date from tbl_dtr where work_date < '2019/09/10' order by Work_date asc) 
from tbl_dtr 
order by Work_date desc

3 个答案:

答案 0 :(得分:1)

您需要将子查询用作派生表,并从中进行选择:

// Globals
const TIMERS = {}; // holds timers

calculate(); // First run (populate on load)


// Link Inputs
let inputsArray = document.querySelectorAll('input');
inputsArray.forEach(el => el.addEventListener('input', linkValue));


function calculate(){

  /*
  A = final balance
  P = principal
  r = rate
  n = number of annual interst payments
  t = years
  */

  // Calculations
  let P = parseFloat(document.querySelector('#calc_P').value);
  let r = document.querySelector('#calc_r').value / 100;
  let n = 12;
  let t = parseFloat(document.querySelector('#calc_t').value);
  let A = parseFloat(document.querySelector('#calc_A').value);
  let p = 12;

  let nper = p * t;
  let rate = (1 + r / n) ** (n / p) - 1;
  let F = P * (1 + rate) ** nper + (A * ((1 + rate) ** nper - 1)) / rate;


  // Initialize
  document.querySelector('#finalValue').innerHTML = F.toFixed(2);

  // Fields that will require special formatting (rounding)
  let roundFields = ['interest','totInterest','balance'];

  // Seed Data
  let data = [{
    period: 0,
    payment: P || 0,
    totPayment: P || 10000,
    interest: 0,
    totInterest: 0,
    balance: P || 10000
  }];

  // Create Data Objects
  for (let i = 1; i < nper + 1; i++) {
    let prevRow = i-1;
    let interest = data[prevRow].balance * rate;

    data.push({
      period      : i,
      payment     : A,
      totPayment  : (P += A),
      interest    : interest,
      totInterest : data[prevRow].totInterest + interest,
      balance     : data[prevRow].balance + A + interest
    });
  }




  //************* CREATE HTML TABLE *************

  let tableSelector = '#TblCalc';

  buildHtmlTable(data, tableSelector);


  function buildHtmlTable(data, tableSelector) {

    let fragment = document.createDocumentFragment();
    let table    = addElement(fragment, 'table', 'table table-sm table-hover tbl-container');
    let thead    = addElement(table, 'thead', 'thead-dark');
    let header   = addElement(thead, 'tr', 'tbl-headers');
    let tbody    = addElement(table, 'tbody');

    // Create Headers
    for (let propertyName in data[0]) {
      let th = addElement(header, 'th'); 
      addText(th, propertyName);
    }

    // Create Rows
    data.forEach((item,i,array)=>{

      let tr = addElement(tbody, 'tr', 'tbl-row');

      // Create Cells
      for (let key in item) {
        let td  = addElement(tr, 'td');
        let val = item[key];
        
        // format output for float fields
        if (roundFields.includes(key))
          val = round(val).toFixed(2);

        addText(td, '' + val);
      }


    }); // End: Create Rows


    // Add to DOM
    let target = document.querySelector(tableSelector);
    target.innerHTML = '';
    target.appendChild(fragment);
  }
  
}


//************ Event Handlers *************

// Link the range with number inputs
function linkValue(e) {
  let target = e.target;
  
  if( typeof target['linkedElement'] !== 'undefined' ){
    target['linkedElement'].value = target.value;
  }
  else {
  
    let ancestor = target.closest('.row');
    let inputs   = ancestor.querySelectorAll('input');

    for (let input of inputs){
      if (target !== input){
        // establish bi-directional links
        target['linkedElement'] = input;
        input['linkedElement'] = target;

        // set values
        input.value = target.value;
        
        calculate();
        break;
      }
    }
  }
  
  // Reduce lag for certain sliders by adding a timeout
  if (target.type == 'range' ){
    if ( ['calc_t','calc_r'].includes(target.id) || 
         ['calc_t','calc_r'].includes(target.linkedElement.id) ){ 
      let id = 'range';

      // clear any open timers (stop unecessarily generating table)
      if (TIMERS[id]){
        clearTimeout(TIMERS[id]);
        TIMERS[id] = null;
      }

      TIMERS[id] = window.setTimeout(function(id){
        calculate();
        TIMERS[id]=null;
      }.bind(this,id), 10);
    }
    else {
      // not all sliders require a delay
      calculate();
    }
  }
  else {
    // immediately execute
    calculate();
  }
}




//************ Utility Functions *************

function addElement(parent, nodeName, className) {
  let element = document.createElement(nodeName);
  if (className) element.className = className;
  if (parent) parent.appendChild(element);
  return element;
}

function addText(parent, text) {
  parent.appendChild( document.createTextNode(text) );
}

function round(num){
  return Math.round( ( num + Number.EPSILON ) * 100 ) / 100;
}

答案 1 :(得分:1)

您可以使用offset并获取下一行:

AudioBufferSourceNode

通过这种方式,您告诉SQL跳过4条记录并返回下1行

答案 2 :(得分:-1)

为方便查询,您还可以使用OFFSETLIMIT

SELECT Work_date
FROM tbl_dtr
WHERE work_date < '2019/09/10'
ORDER BY Work_date asc
LIMIT 1 -- only get 1 record
OFFSET 4 -- skip first for records, thus retrieving the 5th. Replace this with n-1